diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..5f188a8a --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 NonLegit + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 58beeacc..fd0fbf0a 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,538 @@ -# Getting Started with Create React App +
+ + +# NonLegit + -This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). +
+
+ logo -## Available Scripts -In the project directory, you can run: +### โ€Lets Go, Start New Adventure.โšกโ€œ + +
+ +

+
+

-### `npm start` +## Table of Contents -Runs the app in the development mode.\ -Open [http://localhost:3000](http://localhost:3000) to view it in your browser. +- ๐Ÿ“™ Overview +- ๐Ÿ’ป Get Started +- ๐ŸŒŽ Build & deployment +- ๐Ÿ” Features +- ๐Ÿ“ฝ GIF Demo +- โœจ Contributors +- ๐Ÿ”’ License +
-The page will reload when you make changes.\ -You may also see any lint errors in the console. +## Overview -### `npm test` + +
+ +## Get Started + +
    +
  1. Clone the repository + +
    + +``` +git clone https://github.com/NonLegit/Front-End/tree/main +``` + +
  2. +
  3. Run json server + +
    + +``` +npm run server-json +``` +
  4. +
  5. Run the program + +
    + +``` +npm run start +``` +
  6. +
  7. Build functional document + +
    + +``` +npm run docs +``` +
  8. +
  9. Build test document + +
    + +``` +npm run test +``` +
  10. +
+
+ + + +## Build & Deployment + +There are a few additional environment variables that are used when building and deploying for production. + +1. `REACT_APP_GOOGLECLIENTID`: A environment string used in connecting with google client. +1. `REACT_APP_FACEBOOKCLIENTID`:A environment string used in connecting with facebook client. +1. `REACT_APP_SITEKEY`: A environment string used in google captcha.. +1. `REACT_APP_ENV`: An environment string. Currently it is only used to differentiate different deploys (development or production). +1. `REACT_APP_PROXY_DEVELOPMENT`: The base URL of the development server. default value is `http://localhost:8000`. +1. `REACT_APP_PROXY_PRODUCTION`: The base URL of the backend + + +
+ + + +## Features + + +
+ Features + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureScreenShotDescription
+๐Ÿ”ท Authentication + + + logo + +
    +
  • Login
  • +
  • Sign-up
  • +
  • Sign-up with Google and Facebook
  • +
  • Reset Password
  • +
  • Forget User Name
  • +
+
๐Ÿ”ถ Create Post + +logo + + +

1) You con create 3 types of post

+
    +
  • ๐Ÿ“ Text: you can add text and styling it with fancy text editor
  • +
  • ๐Ÿ“ท mage: you can upload photo or video to add to your post
  • +
  • ๐Ÿ“Ž Link: you can add link to your post
  • +
+

2) You con add 2 tag to your post

+
    +
  • ๐Ÿ”ž NSFW
  • +
  • ๐Ÿ’ฅ spoiler
  • +
+
๐Ÿ”ท Search + + logo +

The search results have 4 types

+
    +
  • ๐Ÿ“ซ Posts
  • +
  • ๐Ÿ’ญ Comments
  • +
  • ๐Ÿ‘จโ€๐Ÿ‘ง Communities
  • +
  • ๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ People
  • +
+
๐Ÿ”ถ User Actions + +logo + +

You con do actions on posts like

+
    +
  • โ Upvote & Downvote
  • +
  • โคด Share
  • +
  • โœ’ Edit post
  • +
  • โœ… Approve (if you are moderator)
  • +
  • ๐Ÿ•ณ Spam
  • +
  • ๐Ÿ™ˆ Hidden
  • +
  • ๐Ÿ”ฑ Save
  • +
  • ๐Ÿšซ Delete (if you are moderator or creator post)
  • +
  • ๐Ÿ”’ Lock (if you are moderator or creator post)
  • +
+
๐Ÿ”ท Comments + +logo + +

1) ๐Ÿ–‡ Multilevel Comments

+

3) Actions on posts:

+
    +
  • โ Upvote & Downvote
  • +
  • โœ… Approve (if you are moderator)
  • +
  • ๐Ÿ•ณ Spam
  • +
  • ๐Ÿ”ฑ Save
  • +
  • ๐Ÿ—ฏ Replay
  • +
+
๐Ÿ”ถ Settings + +logo + +
    +
  • +

    ๐Ÿšน Account

    +
      +
    • You can change (Email, Password, Gender, Country)

    • +
    • +

      Delete Account

    • +
    • +

      Connect with google

    • +
    +
  • +
  • +

    ๐Ÿ‘ค Profile

    +
      +
    • You can Edit (name , about, Profile picture, Background Picture)

    • +
    • +

      You can on/off (NSFW, allow people to follow you)

    • +
    • +

      You can add social links to other website

    • +
    +
  • + +
  • +

    ๐Ÿšจ Safety and privacy

    +
      +
    • ๐Ÿ”ˆ You can block and unblock user

    • +
    • +

      You can see block list

    • +
    +
  • + +
  • +

    โšก Feed Settings

    +
      +
    • You can on/off (Adult content, autoplay media)

    • +
    +
  • +
+
๐Ÿ”ท Notifications + +logo + +

1) ๐Ÿ™ˆ You con hide notification

+

2) Types Notification:

+
    +
  • New Followers
  • +
  • Replies
  • +
+
๐Ÿ”ถ Profile + +logo + +

You con view

+
    +
  • ๐Ÿ” Overview: you can see activity of user
  • +
  • ๐Ÿ“ซ Posts: you can see posts of user
  • +
  • ๐Ÿ—ฏ Comments: you can see comments of user
  • +
  • ๐Ÿ—ƒ History: posts just yo see it
  • +
  • ๐Ÿ“‹ Saved: posts and comments you saved it
  • +
  • ๐Ÿ™ˆ Hidden: posts you hide it
  • +
  • ๐Ÿ‘ Upvote: posts you upvote it
  • +
  • ๐Ÿ‘Ž Downvote: posts you downvote it
  • +
+
๐Ÿ”ท Subreddit + +logo + +

1) ๐Ÿ”ฐ You con create Subreddit

+

2) ๐Ÿ‘€ View posts of Subreddit

+

3) ๐Ÿคœ๐Ÿผ join or leave Subreddit

+

4) Subreddit types:

+
    +
  • ๐Ÿ‘ท๐Ÿผโ€โ™‚๏ธ Public: Anyone can view, post, and comment to this community
  • +
  • ๐Ÿ‘โ€๐Ÿ—จ Restricted: Anyone can view this community, but only approved users can post
  • +
  • ๐Ÿ”’ Private: Only approved users can view and submit to this community
  • +
+
๐Ÿ”ถ Moderation + +logo + +

In Moderation page, you can control:

+
    +
  • ๐Ÿ•ณ Spam: you can control spam posts
  • +
  • โœ’ Edited: you can control edited posts
  • +
  • ๐Ÿ’ˆ Unmoderator: you can control unmoderator posts
  • +
  • ๐Ÿšซ BANNED: you can ban users
  • +
  • ๐Ÿ”ˆ MUTED: you can mute users
  • +
  • โœ… APPROVED: you can add new moderators
  • +
  • ๐Ÿ‘จ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป MODERATORS: you can edit access to moderators
  • +
  • ๐ŸŽจ POST FLAIR: you can edit flair and make new flairs
  • +
  • ๐Ÿšง RULES: you can add new rules to subreddit
  • +
  • ๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ COMMUNITY: you can edit (name of subreddit, community topics, community description, region, type of community)
  • +
  • ๐Ÿ’ญ POSTS AND COMMENTS: you can control type of posts
  • +
+
๐Ÿ”ท Messages + +logo + +

1) ๐Ÿ“ฉ Message Form (Send a private message)

+

2) ๐Ÿ“ฎ Sent Messages: message which you sent

+

3) ๐Ÿ“ฆ Inbox :

+
    +
  • All: All messages
  • +
  • Unread: message which you didn't read it
  • +
  • Messages : message which you receive
  • +
  • Post replies: replies to your posts
  • +
+
๐Ÿ”ถ Push Notifications + +logo + +

1) ๐Ÿ’Œ Notifications and messages

+

2) ๐Ÿ”“ You must give permission to push notifications

+

3) Push Notifications types:

+
    +
  • Foreground
  • +
  • Background
  • +
+
๐Ÿ”ท Top Communities + +logo + +

๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง View top communities by categories

+
๐Ÿ”ถ Pages + +logo + +
    +
  • +

    Home page

    +
  • +
  • +

    Popular

  • +
  • +

    ALL

  • +
  • +

    Explorer

  • +
+
๐Ÿ”ท Listing + +logo + +

You can sort posts

+
    +
  • Hot
  • +
  • Top
  • +
  • New
  • +
  • Hot
  • +
+
+ +
+ + +## GIF Demo + + + + + + + + + + +
VideoContent
+ + +
    +
  • Authentication
  • +
  • Comments
  • +
  • Notification
  • +
  • Messages
  • +
  • Settings
  • +
+
+
+ + + + + + +
+ + +
    +
  • Home page
  • +
  • Posts
  • +
  • Create Post
  • +
+
+
+ + + + + + +
+ + +
    +
  • My profile
  • +
  • Other Profile
  • +
  • Moderation
  • +
  • Top Communities
  • +
+
+
+ + + + + +
+ + +
    +
  • Create Subreddit
  • +
  • Subreddit
  • +
  • Moderation
  • +
  • Search
  • +
  • Explorer
  • +
+
+ + + +
+ +## Contributors + + + + + + + + + + +

Nour Ziad Almulhem


Basma Elhoseny


Fady Adel


Ahmed Hosny


Adham Ali

+

Eslam Ashraf

+ +## ๐Ÿ”’ License + +> **Note**: This software is licensed under MIT License, See [License](https://github.com/NonLegit/Front-End/blob/development/LICENSE) for more information ยฉNonLegit. diff --git a/[Software Engineering] Project F2022.pdf b/[Software Engineering] Project F2022.pdf new file mode 100644 index 00000000..18fa5a0b Binary files /dev/null and b/[Software Engineering] Project F2022.pdf differ diff --git a/data/AddFlair.json b/data/AddFlair.json new file mode 100644 index 00000000..544b7b4d --- /dev/null +++ b/data/AddFlair.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/data/AddRule.json b/data/AddRule.json new file mode 100644 index 00000000..544b7b4d --- /dev/null +++ b/data/AddRule.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/data/EditFliar.json b/data/EditFliar.json new file mode 100644 index 00000000..544b7b4d --- /dev/null +++ b/data/EditFliar.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/data/MessageDrive.json b/data/MessageDrive.json new file mode 100644 index 00000000..9979c1af --- /dev/null +++ b/data/MessageDrive.json @@ -0,0 +1,234 @@ +{ + "status": "success", + "data": [ + { + "_id": "639d098f025d17f64e8c0c1e11", + "subject": { + "text": "Hello Eslam", + "_id": "639d098f025d17f64e8c0c1f" + }, + "text": "Can I call You?", + "type": "userMessage", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Fady" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + }, + { + "_id": "639d098f025d17f64e8c0c1e22", + "subject": { + "text": "Hello Eslam", + "_id": "639d098f025d17f64e8c0c1f" + }, + "text": "Messi is hereeeeeee", + "type": "userMessage", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Esalm" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + }, + { + "_id": "639d098f025d17f64e8c0c1e33", + "subject": { + "text": "Hello Eslam", + "_id": "639d098f025d17f64e8c0c1f" + }, + "text": "I will Wait for going ", + "type": "userMessage", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + } + , + { + "_id": "639d098f025d17f64e8c0c1e1", + "subreddit": { + "_id": "639ce52b71990b53b75f4c7f", + "fixedName": "ESLAM_SUBREDDIT", + "name": "ESLAM_SUBREDDIT", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "type": "subredditBan", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + } + , + { + "_id": "639d098f025d17f64e8c0c1e2", + "subreddit": { + "_id": "639ce52b71990b53b75f4c7f", + "fixedName": "ESLAM_SUBREDDIT", + "name": "ESLAM_SUBREDDIT", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "type": "subredditMute", + "from": { + "_id": "638bed0c01f496d7284c281a3", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + } + , + { + "_id": "639d098f025d17f64e8c0c1e4", + "subreddit": { + "_id": "639ce52b71990b53b75f4c7f", + "fixedName": "ESLAM_SUBREDDIT", + "name": "ESLAM_SUBREDDIT", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "type": "subredditModeratorInvite", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + } + , + { + "_id": "639d098f025d17f64e8c0c1e5", + "subreddit": { + "_id": "639ce52b71990b53b75f4c7f", + "fixedName": "ESLAM_SUBREDDIT", + "name": "ESLAM_SUBREDDIT", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "type": "subredditModeratorRemove", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + } + , + { + "_id": "639d098f025d17f64e8c0c1e6", + "subreddit": { + "_id": "639ce52b71990b53b75f4c7f", + "fixedName": "ESLAM_SUBREDDIT", + "name": "ESLAM_SUBREDDIT", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "type": "subredditApprove", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + },{ + "_id": "639d098f025d17f64e8c0c1e7", + "subject": { + "text": "Hello Eslam", + "_id": "639d098f025d17f64e81f" + }, + "text": "Can I call You?", + "type": "userMessage", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d8", + "userName": "Fady" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + }, + { + "_id": "639d098f025d17f64e8c0c1e9", + "subject": { + "text": "Hello Eslam", + "_id": "639d098f025d17f64e81f" + }, + "text": "Messi is hereeeeeee", + "type": "userMessage", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Esalm" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + } + ] +} \ No newline at end of file diff --git a/data/MessagePostReplay.json b/data/MessagePostReplay.json new file mode 100644 index 00000000..633f223b --- /dev/null +++ b/data/MessagePostReplay.json @@ -0,0 +1,144 @@ +{ + "status": "success", + "data": + [ + { + "_id": "639d0de38957d750a8eee91a", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Fady" + }, + "createdAt": "2022-12-19T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "fady is going to school" + } + }, + { + "_id": "639d0de38957d750a8eee91a55", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Mohab" + }, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "I tired man!!" + } + }, + { + "_id": "639d0de38957d750a8eee91a66", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Fathi" + }, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "testing is done bro!!" + } + }, + { + "_id": "639d0de38957d750a8eee91a88", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Doaa" + }, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "I stuied French" + } + }, + { + "_id": "639d0de38957d750a8eee91a77", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "fady is sending 2" + } + } + ] + +} \ No newline at end of file diff --git a/data/SearchByComments.json b/data/SearchByComments.json new file mode 100644 index 00000000..8f5322da --- /dev/null +++ b/data/SearchByComments.json @@ -0,0 +1,103 @@ + { + "data": [ + { + "_id": "asd", + "author": { + "_id": "asd212", + "userName": "ahmed", + "profilePicture": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/1610059_681891708529379_2132042836_n.jpg?_nc_cat=111&ccb=1-7&_nc_sid=174925&_nc_eui2=AeFisYcHx5f55wofAI89qsv4zwd8DyzyeI7PB3wPLPJ4jmThq4Z2nXImJdnzBzY682Ug8GJmq6pI9RMvTwe9n4Gn&_nc_ohc=njty5Km-D6IAX9S2nST&_nc_ht=scontent.fcai19-6.fna&oh=00_AfCuo4cKDBZx7mLXxK-A1PtFj7RKiSri443Fa8QU-Pb5yw&oe=63C8EB3B", + "displayName": "milk" + }, + "post": { + "_id": "asd212", + "author": { + "_id": "asd212", + "userName": "ahmed", + "profilePicture": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "displayName": "hamada" + }, + "owner": { + "icon": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "_id": "12asda2", + "fixedName": "Nonlegit", + "name": "asdwd", + "membersCount": 123, + "description": "this is my first subreddit" + }, + "title": "first post", + "kind": "image", + "text": "asdasda", + "url": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "images": [ + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2" + ], + "video": "hamada with milk", + "votes": 1200, + "commentCount": 1300, + + "createdAt": "2022-11-12T12:29:28Z", + "flairId": { + "_id": "asd", + "text": "asd", + "backgroundColor": "blue", + "textColor": "red" + } + }, + "text": "aspidasjd;ioajf;sadfs;f adas daspdioasdklsa iodaskl;d jasdj sad iajfhdafhjsd fhad isd ijsa ja;sfh;jal;f h;jasdh uoas'jdash;jhas;fiasj das'jd asj dhuaos;d j;as'dk as jfa;sifj'las sa;dkl jnasjd as;f a;kf as d;asnfajlsf nla'f'klash fas'f ashf a'hf aio'f ha'fh 'ahfl ahsf hdajfjsdbgdalfja ;fdusghf;afh alndsg' hak fkDAJF ldanfl'kaf hal'kfh a'l hf'alsias ihasdh asl'kfjash ahjfhasjf haslf hlas hfa'hslf haf'gaudlfNj'alsh 'g aspidasjd;ioajf;sadfs;f adas daspdioasdklsa iodaskl;d jasdj sad iajfhdafhjsd fhad isd ijsa ja;sfh;jal;f h;jasdh uoas'jdash;jhas;fiasj das'jd asj dhuaos;d j;as'dk as jfa;sifj'las sa;dkl jnasjd as;f a;kf as d;asnfajlsf nla'f'klash fas'f ashf a'hf aio'f ha'fh 'ahfl ahsf hdajfjsdbgdalfja ;fdusghf;afh alndsg' hak fkDAJF ldanfl'kaf hal'kfh a'l hf'alsias ihasdh asl'kfjash ahjfhasjf haslf hlas hfa'hslf haf'gaudlfNj'alsh", + "createdAt": "2022-11-12T12:29:28Z", + "votes": 1200, + "repliesCount": 1222 + }, + { + "_id": "asd", + "author": { + "_id": "asd212", + "userName": "ahmed", + "profilePicture": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/1610059_681891708529379_2132042836_n.jpg?_nc_cat=111&ccb=1-7&_nc_sid=174925&_nc_eui2=AeFisYcHx5f55wofAI89qsv4zwd8DyzyeI7PB3wPLPJ4jmThq4Z2nXImJdnzBzY682Ug8GJmq6pI9RMvTwe9n4Gn&_nc_ohc=njty5Km-D6IAX9S2nST&_nc_ht=scontent.fcai19-6.fna&oh=00_AfCuo4cKDBZx7mLXxK-A1PtFj7RKiSri443Fa8QU-Pb5yw&oe=63C8EB3B", + "displayName": "milk" + }, + "post": { + "_id": "asd212", + "author": { + "_id": "asd212", + "userName": "ahmed", + "profilePicture": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "displayName": "hamada" + }, + "owner": { + "icon": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "_id": "12asda2", + "fixedName": "Nonlegit", + "name": "asdwd", + "membersCount": 123, + "description": "this is my first subreddit" + }, + "title": "first post", + "kind": "image", + "text": "asdasda", + "url": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "images": [ + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2" + ], + "video": "hamada with milk", + "votes": 1200, + "commentCount": 1300, + "createdAt": "2022-11-12T12:29:28Z", + "flairId": { + "_id": "asd", + "text": "asd", + "backgroundColor": "blue", + "textColor": "red" + } + }, + "text": "asdwd", + "createdAt": "2022-11-12T12:29:28Z", + "votes": 1200, + "repliesCount": 1222 + } + ] +} \ No newline at end of file diff --git a/data/SearchByCommunty.json b/data/SearchByCommunty.json new file mode 100644 index 00000000..5451b7e1 --- /dev/null +++ b/data/SearchByCommunty.json @@ -0,0 +1,74 @@ +{ + "data": [ + { + "icon": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "_id": "asd", + "fixedName": "asd", + "membersCount": 123, + "description": "asd", + "name": "asdw", + "nsfw": true, + "isJoined": false + }, + { + "icon": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "_id": "asd", + "fixedName": "asd", + "membersCount": 123, + "description": "asd", + "name": "asdw", + "nsfw": true, + "isJoined": true + }, + { + "icon": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "_id": "asd", + "fixedName": "asd", + "membersCount": 123, + "description": "asd", + "name": "asdw", + "nsfw": true, + "isJoined": true + }, + { + "icon": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "_id": "asd", + "fixedName": "asd", + "membersCount": 123, + "description": "asd", + "name": "asdw", + "nsfw": true, + "isJoined": false + }, + { + "icon": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "_id": "asd", + "fixedName": "asd", + "membersCount": 123, + "description": "asd", + "name": "asdw", + "nsfw": true, + "isJoined": true + }, + { + "icon": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "_id": "asd", + "fixedName": "asd", + "membersCount": 123, + "description": "asd", + "name": "asdw", + "nsfw": true, + "isJoined": true + }, + { + "icon": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "_id": "asd", + "fixedName": "asd", + "membersCount": 123, + "description": "asd", + "name": "asdw", + "nsfw": true, + "isJoined": true + } + ] +} \ No newline at end of file diff --git a/data/SearchByPeople.json b/data/SearchByPeople.json new file mode 100644 index 00000000..c9fd9ad5 --- /dev/null +++ b/data/SearchByPeople.json @@ -0,0 +1,36 @@ +{ + + "data": [ + { + "_id": "ad", + "userName": "ahmed", + "profilePicture": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "displayName": "asd", + "postKarma": 123, + "commentKarma": 123, + "description": "asd", + "isFollowed": true + }, + { + "_id": "ad", + "userName": "ahmed", + "profilePicture": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "displayName": "asd", + "postKarma": 123, + "commentKarma": 123, + "description": "asd", + "isFollowed": false + }, + { + "_id": "ad", + "userName": "ahmed", + "profilePicture": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "displayName": "asd", + "postKarma": 123, + "commentKarma": 123, + "description": "asd", + "isFollowed": true + } + ] + +} \ No newline at end of file diff --git a/data/SearchByPost.json b/data/SearchByPost.json new file mode 100644 index 00000000..735dccc7 --- /dev/null +++ b/data/SearchByPost.json @@ -0,0 +1,148 @@ +{ + + "data": [ + { + "_id": "asd212", + "author": { + "_id": "asd212", + "userName": "ahmed", + "profilePicture": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "displayName": "hamada" + }, + "owner": { + "icon": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "_id": "12asda2", + "fixedName": "Nonlegit", + "name": "asdwd", + "membersCount": 123, + "description": "this is my first subreddit" + }, + "title": "first post", + "kind": "self", + "text": "

asdas

da ", + "url": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "images": [ + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2" + ], + "video": "hamada with milk", + "votes": 1200, + "commentCount": 1300, + "createdAt": "2022-11-12T12:29:28Z", + "flairId": { + "_id": "asd", + "text": "asd", + "backgroundColor": "blue", + "textColor": "red" + } + }, + { + "_id": "asd212", + "author": { + "_id": "asd212", + "userName": "ahmed", + "profilePicture": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "displayName": "hamada" + }, + "owner": { + "icon": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "_id": "12asda2", + "fixedName": "Nonlegit", + "name": "asdwd", + "membersCount": 123, + "description": "this is my first subreddit" + }, + "title": "first post", + "kind": "image", + "text": "asdasda", + "url": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "images": [ + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2" + ], + "video": "hamada with milk", + "votes": 1200, + "commentCount": 1300, + "createdAt": "2022-11-12T12:29:28Z", + "flairId": { + "_id": "asd", + "text": "asd", + "backgroundColor": "blue", + "textColor": "red" + } + }, + { + "_id": "asd212", + "author": { + "_id": "asd212", + "userName": "ahmed", + "profilePicture": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "displayName": "hamada" + }, + "owner": { + "icon": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "_id": "12asda2", + "fixedName": "Nonlegit", + "name": "asdwd", + "membersCount": 123, + "description": "this is my first subreddit" + }, + "title": "first post askdjaskl;djk;lasdasjd;ljsadufslakjdksalfjhdasjdfsajhvkas;jdalghsfaso;idjasghkjc", + "kind": "image", + "text": "askdjklasjdkajskdksaldj;lksaldjsadlkasjdklsajkld;askl;dkas;lkdlaskdl", + "url": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "images": [ + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2" + ], + "video": "hamada with milk", + "votes": 1200, + "commentCount": 1300, + "createdAt": "2022-11-12T12:29:28Z", + "flairId": { + "_id": "asd", + "text": "asd", + "backgroundColor": "blue", + "textColor": "red" + } + }, + { + "_id": "asd212", + "author": { + "_id": "asd212", + "userName": "ahmed", + "profilePicture": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "displayName": "milk" + }, + "owner": { + "icon": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "_id": "asd", + "fixedName": "asd", + "name": "asdwd", + "membersCount": 123, + "description": "asd" + }, + "title": "second post", + "kind": "link", + "text": "asdasda", + "url": "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2", + "images": [ + "https://scontent.fcai19-6.fna.fbcdn.net/v/t1.18169-9/14731344_1268156939902850_4843578088361110846_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=09cbfe&_nc_eui2=AeEky4_3cTAH8AsHcH3UuXIKcLp-k-70xXVwun6T7vTFdcArTit-okcWlHaag26qfJeWLi2DDiYbw59pVU7sfWCM&_nc_ohc=A5SpL8aNUVEAX-YO51A&_nc_oc=AQniPbizNXpZ3SFnkYVS1CpwqCbtRPI2D8DeAHUhOG0t0JSuAtT4Bvl1Xbu4WrCWCn8&_nc_ht=scontent.fcai19-6.fna&oh=00_AfDhRAFvWuZtkXlwquZXICIDBSAhT2eF7HurP0EfQHnCEg&oe=63C6E9D2" + ], + "video": "asdwad", + "votes": 90, + "commentCount": 12, + "createdAt": "2022-11-12T12:29:28Z", + "flairId": { + "_id": "asd", + "text": "asd", + "backgroundColor": "asd", + "textColor": "asd" + } + } + ] + +} \ No newline at end of file diff --git a/data/Subreddit.json b/data/Subreddit.json index 9b509a9d..aba25e01 100644 --- a/data/Subreddit.json +++ b/data/Subreddit.json @@ -44,10 +44,10 @@ "topics": [], "primaryTopic": "Add a Primary Topic", "owner": "638b8c62c20658257a3c450a", - "moderators": [ - { + "moderators": + [{"user": { "id": "638b8c62c20658257a3c450a", - "userName": "nourr", + "userName": "nour", "joiningDate": 1670104113541, "profilePicture": "https://api.nonlegit.click/api/v1/users/images/https://api.nonlegit.click/api/v1/users/images/default.png", "moderatorPermissions": { @@ -57,8 +57,8 @@ "flair": true, "posts": true } - } - ], + }} + ], "flairIds": [] } } \ No newline at end of file diff --git a/data/SubreddtInvitation.json b/data/SubreddtInvitation.json new file mode 100644 index 00000000..0460d167 --- /dev/null +++ b/data/SubreddtInvitation.json @@ -0,0 +1,3 @@ +{ + "status": "success" +} \ No newline at end of file diff --git a/data/approvedList.json b/data/approvedList.json new file mode 100644 index 00000000..1f6c007c --- /dev/null +++ b/data/approvedList.json @@ -0,0 +1,35 @@ +{ + "status": "success", + "data": [ + { + "user": { + "_id": "0", + "userName": "fady", + "joinDate": "2019-08-24T14:15:22Z", + "profilePicture": "https://styles.redditmedia.com/t5_2ql2m/styles/communityIcon_vr02expkpl391.jpg?format=pjpg&s=6fc537d22ab75feda2ea15985e89da63c7564797" + }, + "approvedDate": "2022-12-20T07:58:23.377Z", + "_id": "63a16b1f5de58d167a0d0c82" + }, + { + "user": { + "_id": "0", + "userName": "fady", + "joinDate": "2019-08-24T14:15:22Z", + "profilePicture": "https://styles.redditmedia.com/t5_2ql2m/styles/communityIcon_vr02expkpl391.jpg?format=pjpg&s=6fc537d22ab75feda2ea15985e89da63c7564797" + }, + "approvedDate": "2022-12-20T07:58:23.377Z", + "_id": "63a16b1f5de58d167a0d0c82" + }, + { + "user": { + "_id": "0", + "userName": "fady", + "joinDate": "2019-08-24T14:15:22Z", + "profilePicture": "https://styles.redditmedia.com/t5_2ql2m/styles/communityIcon_vr02expkpl391.jpg?format=pjpg&s=6fc537d22ab75feda2ea15985e89da63c7564797" + }, + "approvedDate": "2022-12-20T07:58:23.377Z", + "_id": "63a16b1f5de58d167a0d0c82" + } + ] +} \ No newline at end of file diff --git a/data/approvedUnapprovedList.json b/data/approvedUnapprovedList.json new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/data/approvedUnapprovedList.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/Settings.json b/data/banUnban.json similarity index 100% rename from Settings.json rename to data/banUnban.json diff --git a/data/banedList.json b/data/banedList.json deleted file mode 100644 index 06d46a93..00000000 --- a/data/banedList.json +++ /dev/null @@ -1,38 +0,0 @@ -[ - { - "_id": "0", - "userName": "fady", - "profilePicture": "https://styles.redditmedia.com/t5_2ql2m/styles/communityIcon_vr02expkpl391.jpg?format=pjpg&s=6fc537d22ab75feda2ea15985e89da63c7564797", - "banDate": "2019-08-24T14:15:22Z", - "baninfo": { - "punish_type": "Spam", - "Note": "", - "punishReason": "string0", - "duration": 0 - } - }, - { - "_id": "1", - "userName": "Eslam", - "profilePicture": "https://styles.redditmedia.com/t5_2ql2m/styles/communityIcon_vr02expkpl391.jpg?format=pjpg&s=6fc537d22ab75feda2ea15985e89da63c7564797", - "banDate": "2019-08-24T14:15:22Z", - "baninfo": { - "punish_type": "Other", - "Note": "string1", - "punishReason": "string1", - "duration": -1 - } - }, - { - "_id": "2", - "userName": "hosny", - "profilePicture": "https://styles.redditmedia.com/t5_2ql2m/styles/communityIcon_vr02expkpl391.jpg?format=pjpg&s=6fc537d22ab75feda2ea15985e89da63c7564797", - "banDate": "2019-08-24T14:15:22Z", - "baninfo": { - "punish_type": "Threatening, Harassing, Or Inciting Violence", - "Note": "string2", - "punishReason": "string2", - "duration": 2 - } - } -] \ No newline at end of file diff --git a/data/bannedList.json b/data/bannedList.json new file mode 100644 index 00000000..8660b48b --- /dev/null +++ b/data/bannedList.json @@ -0,0 +1,119 @@ +{ + "status": "success", + "data": [ + { + "banInfo": { + "punishReason": "No reason", + "punish_type": "No Spoiler", + "Note": "he is bad person", + "duration": 20 + }, + "muteInfo": { + "muteMessage": "Spammer" + }, + "user": { + "_id": "63a107a3e72289e28e6b760d", + "userName": "fady", + "joinDate": "2022-12-20T00:53:55.071Z", + "profilePicture": "users/default.png" + }, + "type": "banned", + "_id": "63a16ea36cdd7a6f4e7ace09" + }, + { + "banInfo": { + "punishReason": "No reason", + "punish_type": "No Spoiler", + "Note": "he is bad person", + "duration": 20 + }, + "muteInfo": { + "muteMessage": "Spammer" + }, + "user": { + "_id": "63a107a3e72289e28e6b760d", + "userName": "fady", + "joinDate": "2022-12-20T00:53:55.071Z", + "profilePicture": "users/default.png" + }, + "type": "banned", + "_id": "63a16ea36cdd7a6f4e7ace09" + }, + { + "banInfo": { + "punishReason": "No reason", + "punish_type": "No Spoiler", + "Note": "he is bad person", + "duration": 20 + }, + "muteInfo": { + "muteMessage": "Spammer" + }, + "user": { + "_id": "63a107a3e72289e28e6b760d", + "userName": "lol", + "joinDate": "2022-12-20T00:53:55.071Z", + "profilePicture": "users/default.png" + }, + "type": "banned", + "_id": "63a16ea36cdd7a6f4e7ace09" + }, + { + "banInfo": { + "punishReason": "No reason", + "punish_type": "No Spoiler", + "Note": "he is bad person", + "duration": 20 + }, + "muteInfo": { + "muteMessage": "Spammer" + }, + "user": { + "_id": "63a107a3e72289e28e6b760d", + "userName": "Nour", + "joinDate": "2022-12-20T00:53:55.071Z", + "profilePicture": "users/default.png" + }, + "type": "muted", + "_id": "63a16ea36cdd7a6f4e7ace09" + }, + { + "banInfo": { + "punishReason": "No reason", + "punish_type": "No Spoiler", + "Note": "he is bad person", + "duration": 20 + }, + "muteInfo": { + "muteMessage": "Spammer" + }, + "user": { + "_id": "63a107a3e72289e28e6b760d", + "userName": "Nour", + "joinDate": "2022-12-20T00:53:55.071Z", + "profilePicture": "users/default.png" + }, + "type": "muted", + "_id": "63a16ea36cdd7a6f4e7ace09" + }, + { + "banInfo": { + "punishReason": "No reason", + "punish_type": "No Spoiler", + "Note": "he is bad person", + "duration": 20 + }, + "muteInfo": { + "muteMessage": "Spammer" + }, + "user": { + "_id": "63a107a3e72289e28e6b760d", + "userName": "Nour", + "joinDate": "2022-12-20T00:53:55.071Z", + "profilePicture": "users/default.png" + }, + "type": "muted", + "_id": "63a16ea36cdd7a6f4e7ace09" + } + ] + } \ No newline at end of file diff --git a/data/changeEmail.json b/data/changeEmail.json new file mode 100644 index 00000000..f1981f19 --- /dev/null +++ b/data/changeEmail.json @@ -0,0 +1,3 @@ +{ +"status": "success" +} \ No newline at end of file diff --git a/data/changePassword.json b/data/changePassword.json new file mode 100644 index 00000000..f1981f19 --- /dev/null +++ b/data/changePassword.json @@ -0,0 +1,3 @@ +{ +"status": "success" +} \ No newline at end of file diff --git a/data/createcomment.json b/data/createcomment.json index 7b877ca1..a50547d1 100644 --- a/data/createcomment.json +++ b/data/createcomment.json @@ -1,29 +1,26 @@ { - "status": "success", - "data": { - "comment": { - "_id": "12520", - "author": "string", - "post": "string", - "mentions": [ - "string" - ], - "replies": [ - ], - "moreReplies": { - "count": 0, - "children": [ - "string" - ], - "parentID": "string", - "depth": 0 - }, - "parent": "string", - "parentType": "string", - "text": "string", - "createdAt": "2022-07-21T17:32:28Z", - "votes": 0, - "repliesCount": 0 - } - } - } \ No newline at end of file + "status": "success", + "data": { + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png" + }, + "post": "63a54e2410ebdf1da11b4b81", + "mentions": [], + "replies": [], + "parent": "63a54e2410ebdf1da11b4b81", + "parentType": "Post", + "text": "

New Comment Added

", + "createdAt": "2022-12-23T08:13:27.079Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 0, + "locked": false, + "modState": "unmoderated", + "_id": "63a5632710ebdf1da11b5e7a", + "sortOnHot": 835891603539.5, + "__v": 0 + } +} \ No newline at end of file diff --git a/data/deleteAccount.json b/data/deleteAccount.json new file mode 100644 index 00000000..f1981f19 --- /dev/null +++ b/data/deleteAccount.json @@ -0,0 +1,3 @@ +{ +"status": "success" +} \ No newline at end of file diff --git a/data/editcomment.json b/data/editcomment.json new file mode 100644 index 00000000..a6602e7c --- /dev/null +++ b/data/editcomment.json @@ -0,0 +1,21 @@ +{ + "status": "success", + "data": { + "_id": "63a5613e10ebdf1da11b592e", + "author": "63a2174cbe566ac6458d2c1c", + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [], + "parent": "63a560de10ebdf1da11b581b", + "parentType": "Post", + "text": "

Comment 7 Edited :D

", + "createdAt": "2022-12-23T08:05:18.865Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 0, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891359432.5, + "__v": 0 + } +} \ No newline at end of file diff --git a/data/editpost.json b/data/editpost.json new file mode 100644 index 00000000..9df7d110 --- /dev/null +++ b/data/editpost.json @@ -0,0 +1,39 @@ +{ + "status": "success", + "data": { + "_id": "63a560de10ebdf1da11b581b", + "owner": "63a2174cbe566ac6458d2c1c", + "ownerType": "User", + "author": "63a2174cbe566ac6458d2c1c", + "replies": [ + "63a560ed10ebdf1da11b5884", + "63a560f610ebdf1da11b5898", + "63a560fa10ebdf1da11b58ac", + "63a5613110ebdf1da11b58f2", + "63a5613510ebdf1da11b5906", + "63a5613b10ebdf1da11b591a", + "63a5613e10ebdf1da11b592e" + ], + "title": "New Post", + "kind": "self", + "text": "

Hello :D Edited

", + "url": "", + "images": [], + "createdAt": "2022-12-23T08:03:42.168Z", + "locked": false, + "isDeleted": false, + "sendReplies": true, + "nsfw": false, + "spoiler": false, + "votes": 0, + "views": 0, + "commentCount": 17, + "suggestedSort": "new", + "scheduled": false, + "modState": "unmoderated", + "spamCount": 0, + "spammedBy": [], + "sortOnHot": 835891311084, + "__v": 0 + } +} \ No newline at end of file diff --git a/data/getpost.json b/data/getpost.json index a048d620..b0a6b456 100644 --- a/data/getpost.json +++ b/data/getpost.json @@ -1,14 +1,23 @@ { "status": "OK", "data": { - "_id": "639b5661106f0cd6ca989fdd", + "_id": "63a560de10ebdf1da11b581b", "ownerType": "User", - "replies": [], - "title": "My First Post", + "replies": [ + "63a560ed10ebdf1da11b5884", + "63a560f610ebdf1da11b5898", + "63a560fa10ebdf1da11b58ac", + "63a5613110ebdf1da11b58f2", + "63a5613510ebdf1da11b5906", + "63a5613b10ebdf1da11b591a", + "63a5613e10ebdf1da11b592e" + ], + "title": "New Post", "kind": "self", - "text": "

HeloooooooooooooooooBasmaa :)

\n", + "text": "

Hello :D

", "url": "", - "createdAt": "2022-12-15T06:09:24.932Z", + "images": [], + "createdAt": "2022-12-23T08:03:42.168Z", "locked": false, "isDeleted": false, "sendReplies": true, @@ -16,29 +25,25 @@ "spoiler": false, "votes": 0, "views": 0, - "commentCount": 10, - "shareCount": 0, + "commentCount": 17, "suggestedSort": "new", "scheduled": false, "modState": "unmoderated", "spamCount": 0, "spammedBy": [], - "images": [], - "videos": [], - "sortOnHot": 835542282466, - "sortOnBest": 668433825972.8, + "sortOnHot": 835891311084, "__v": 0, "owner": { - "_id": "639a5cbc1c0d09e8648693d7", + "_id": "63a2174cbe566ac6458d2c1c", "name": "Basma", - "icon": "https://api.nonlegit.click/users/default.png" + "icon": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg" }, "author": { - "_id": "639a5cbc1c0d09e8648693d7", + "_id": "63a2174cbe566ac6458d2c1c", "name": "Basma" }, "isSaved": false, - "postVoteStatus": "0", + "postVoteStatus": 0, "isSpam": false } } \ No newline at end of file diff --git a/data/index.js b/data/index.js index f5bf2711..1ee07c00 100644 --- a/data/index.js +++ b/data/index.js @@ -1,6 +1,7 @@ const { top, best, hot, newPosts, } = require('./homePagePosts.json'); +const { posts } = require('./submitPost.json'); const { subredditsHomePage } = require('./createPostSubreddits.json'); const { usernameAvailable } = require('./usernameAvailability.json'); const homePageCommunities = require('./homePageCommunities.json'); @@ -39,13 +40,8 @@ const markAsRead = require('./markAsRead.json'); const follow = require('./follow.json'); const block = require('./block.json'); const followers = require('./followers.json'); -const deleteAction = require('./deleteAction.json'); const actionOnPost = require('./actionOnPost.json'); const commentsTap = require('./commentsTap.json'); -const getPost = require('./getpost.json'); -const createcomment = require('./createcomment.json'); -const postComments = require('./postcomments.json'); -const moreComments = require('./moreComments.json'); const save = require('./save.json'); const unsave = require('./unsave.json'); const hide = require('./hide.json'); @@ -56,15 +52,58 @@ const moderatorAction = require('./moderatorAction.json'); const UpdateFlair = require('./UpdateFlair.json'); const exploreCommunities = require('./exploreCommunities.json'); const TopCommunities = require('./topCommunities.json'); +const SearchByPeople = require('./SearchByPeople.json'); +const SearchByPost = require('./SearchByPost.json'); +const SearchByComments = require('./SearchByComments.json'); + +const SearchByCommunity = require('./SearchByCommunty.json'); +const AddFlair = require('./AddFlair.json'); +const EditFlair = require('./EditFliar.json'); +const AddRule = require('./AddRule.json'); +const EditRule = require('./AddRule.json'); + const listBlock = require('./listBlock.json'); const notificationToken = require('./notificationToken.json'); -const baned = require('./banedList.json'); +const messageSent = require('./messageSent.json'); +const MessagePostReplay = require('./MessagePostReplay.json'); +const messageRemove = require('./messageRemove.json'); +const MessageDrive = require('./MessageDrive.json'); +const MessageReplay = require('./messageReplay.json'); +const messagesAll = require('./messagesAll.json'); const modQueue = require('./modQueue.json'); const commentMod = require('./commentMod.json'); +const banned = require('./bannedList.json'); +const muted = require('./mutedList.json'); +const moderators = require('./moderatorsList.json'); +const approved = require('./approvedList.json'); +const muteUnmute = require('./muteUnmuteList.json'); +const approvedUnapproved = require('./approvedUnapprovedList.json'); +const banUnban = require('./banUnban.json'); +const invitedModerators = require('./invitedModerators.json'); +const messageUnread = require('./messageUnread.json'); +const messageAsRead = require('./messageAsRead.json'); +const changeEmail = require('./changeEmail.json'); +const changePassword = require('./changePassword.json'); +const deleteAccount = require('./deleteAccount.json'); +const verifyEmail = require('./verifyEmail.json'); +const SubreddtInvitation = require('./SubreddtInvitation.json'); + +const getPost = require('./getpost.json'); +const createcomment = require('./createcomment.json'); +const postComments = require('./postcomments.json'); +const moreComments = require('./moreComments.json'); +const editcomment = require('./editcomment.json'); +const morereplies = require('./morereplies.json'); +const invite = require('./invite.json'); // Something more module.exports = () => ({ - + SearchByComments, + SearchByPost, + EditRule, + AddRule, + EditFlair, + AddFlair, UpdateFlair, userInfo, Subreddit, @@ -106,13 +145,8 @@ module.exports = () => ({ follow, block, followers, - deleteAction, actionOnPost, commentsTap, - getPost, - createcomment, - postComments, - moreComments, subredditFlairs, save, unsave, @@ -123,11 +157,44 @@ module.exports = () => ({ listBlock, notificationToken, moderatorAction, + exploreCommunities, TopCommunities, - baned, + messageSent, + MessagePostReplay, + messageRemove, + MessageDrive, + MessageReplay, + messagesAll, + homePageCommunities, modQueue, commentMod, + SearchByPeople, + SearchByCommunity, + banned, + muted, + moderators, + approved, + muteUnmute, + approvedUnapproved, + banUnban, + invitedModerators, + posts, + messageUnread, + messageAsRead, + changeEmail, + changePassword, + deleteAccount, + verifyEmail, + SubreddtInvitation, + + getPost, + createcomment, + postComments, + moreComments, + editcomment, + morereplies, + invite, // Something more }); diff --git a/routes.json b/data/invite.json similarity index 100% rename from routes.json rename to data/invite.json diff --git a/data/invitedModerators.json b/data/invitedModerators.json new file mode 100644 index 00000000..e5ddfad5 --- /dev/null +++ b/data/invitedModerators.json @@ -0,0 +1,53 @@ +{ + "status": "success", + "data": [ + { + "moderatorPermissions": { + "all": true, + "access": true, + "config": true, + "flair": true, + "posts": true + }, + "user": { + "_id": "0", + "userName": "fady", + "joinDate": "2019-08-24T14:15:22Z", + "profilePicture": "https://styles.redditmedia.com/t5_2ql2m/styles/communityIcon_vr02expkpl391.jpg?format=pjpg&s=6fc537d22ab75feda2ea15985e89da63c7564797" + }, + "_id": "63a16e536cdd7a6f4e7acdb2" + }, + { + "moderatorPermissions": { + "all": true, + "access": true, + "config": true, + "flair": true, + "posts": true + }, + "user": { + "_id": "0", + "userName": "fady", + "joinDate": "2019-08-24T14:15:22Z", + "profilePicture": "https://styles.redditmedia.com/t5_2ql2m/styles/communityIcon_vr02expkpl391.jpg?format=pjpg&s=6fc537d22ab75feda2ea15985e89da63c7564797" + }, + "_id": "63a16e536cdd7a6f4e7acdb2" + }, + { + "moderatorPermissions": { + "all": true, + "access": true, + "config": true, + "flair": true, + "posts": true + }, + "user": { + "_id": "0", + "userName": "fady", + "joinDate": "2019-08-24T14:15:22Z", + "profilePicture": "https://styles.redditmedia.com/t5_2ql2m/styles/communityIcon_vr02expkpl391.jpg?format=pjpg&s=6fc537d22ab75feda2ea15985e89da63c7564797" + }, + "_id": "63a16e536cdd7a6f4e7acdb2" + } + ] +} \ No newline at end of file diff --git a/data/messageAsRead.json b/data/messageAsRead.json new file mode 100644 index 00000000..f1981f19 --- /dev/null +++ b/data/messageAsRead.json @@ -0,0 +1,3 @@ +{ +"status": "success" +} \ No newline at end of file diff --git a/data/messageRemove.json b/data/messageRemove.json new file mode 100644 index 00000000..f1981f19 --- /dev/null +++ b/data/messageRemove.json @@ -0,0 +1,3 @@ +{ +"status": "success" +} \ No newline at end of file diff --git a/data/messageReplay.json b/data/messageReplay.json new file mode 100644 index 00000000..522305c4 --- /dev/null +++ b/data/messageReplay.json @@ -0,0 +1,3 @@ +{ + "status": "success" +} \ No newline at end of file diff --git a/data/messageSent.json b/data/messageSent.json new file mode 100644 index 00000000..c72e1ca8 --- /dev/null +++ b/data/messageSent.json @@ -0,0 +1,70 @@ +{ + "status": "success", + "data": +[ + { + "_id": "639d098f025d17f64e8c0c1e", + "subject": { + "text": "Hello Eslam", + "_id": "639d098f025d17f64e8c0c1f" + }, + "text": "Can I call You?", + "type": "userMessage", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Fady" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + }, + { + "_id": "639d098f025d17f64e8c0c1e", + "subject": { + "text": "Worled Cup", + "_id": "639d098f025d17f64e8c0c1f" + }, + "text": "Messi is hereeeeeee", + "type": "userMessage", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Esalm" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + }, + { + "_id": "639d098f025d17f64e8c0c1e", + "subject": { + "text": "GO to Club", + "_id": "639d098f025d17f64e8c0c1f" + }, + "text": "I will Wait for going ", + "type": "userMessage", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + } + +] +} \ No newline at end of file diff --git a/data/messageUnread.json b/data/messageUnread.json new file mode 100644 index 00000000..8043e3f1 --- /dev/null +++ b/data/messageUnread.json @@ -0,0 +1,172 @@ +{ + "status": "success", + "data": + [ + { + "_id": "639d0de38957d750a8eee91a66", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Fathi" + }, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "testing is done bro!!" + } + }, + { + "_id": "639d0de38957d750a8eee91a88", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Doaa" + }, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "I stuied French" + } + }, + { + "_id": "639d0de38957d750a8eee91a77", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "fady is sending 2" + } + }, { + "_id": "639d0de38957d750a8eee91a", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Fady" + }, + "createdAt": "2022-12-19T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "fady is going to school" + } + }, + { + "_id": "639d0de38957d750a8eee91a55", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Mohab" + }, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "I tired man!!" + } + }, + { + "_id": "639d0de38957d750a8eee91a66", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Fathi" + }, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "testing is done bro!!" + } + } + ] + +} \ No newline at end of file diff --git a/data/messagesAll.json b/data/messagesAll.json new file mode 100644 index 00000000..52be3016 --- /dev/null +++ b/data/messagesAll.json @@ -0,0 +1,508 @@ +{ + "status": "success", + "data": + [ + { + "_id": "639d0de38957d750a8eee91a", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Fady" + }, + "createdAt": "2022-12-19T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "fady is going to school" + } + }, + { + "_id": "639d0de38957d750a8eee91a55", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Mohab" + }, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "I tired man!!" + } + }, + { + "_id": "639d0de38957d750a8eee91a66", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Fathi" + }, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "testing is done bro!!" + } + }, + { + "_id": "639d0de38957d750a8eee91a88", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Doaa" + }, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "I stuied French" + } + }, + { + "_id": "639d0de38957d750a8eee91a77", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "fady is sending 2" + } + }, { + "_id": "639d0de38957d750a8eee91a", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Fady" + }, + "createdAt": "2022-12-19T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "fady is going to school" + } + }, + { + "_id": "639d0de38957d750a8eee91a55", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Mohab" + }, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "I tired man!!" + } + }, + { + "_id": "639d0de38957d750a8eee91a66", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Fathi" + }, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "testing is done bro!!" + } + }, + { + "_id": "639d0de38957d750a8eee91a88", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Doaa" + }, + "subreddit": { + "_id": "63a16a2f5ded3e931da85214", + "fixedName": "BNHA", + "name": "BNHA", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "I stuied French" + } + }, + { + "_id": "639d0de38957d750a8eee91a77", + "type": "postReply", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Eslam" + }, + "to": { + "_id": "638bed0901f496d7284c2810", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:26:05.666Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false, + "comment": { + "_id": "639d0de38957d750a8eee914", + "parent": "6397350b02c3e344ea207064", + "text": "fady is sending 2" + } + }, { + "_id": "639d098f025d17f64e8c0c1e11", + "subject": { + "text": "Hello Eslam", + "_id": "639d098f025d17f64e8c0c1f" + }, + "text": "Can I call You?", + "type": "userMessage", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Fady" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + }, + { + "_id": "639d098f025d17f64e8c0c1e22", + "subject": { + "text": "Hello Eslam", + "_id": "639d098f025d17f64e8c0c1f" + }, + "text": "Messi is hereeeeeee", + "type": "userMessage", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Esalm" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + }, + { + "_id": "639d098f025d17f64e8c0c1e33", + "subject": { + "text": "Hello Eslam", + "_id": "639d098f025d17f64e8c0c1f" + }, + "text": "I will Wait for going ", + "type": "userMessage", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + } + , + { + "_id": "639d098f025d17f64e8c0c1e1", + "subreddit": { + "_id": "639ce52b71990b53b75f4c7f", + "fixedName": "ESLAM_SUBREDDIT", + "name": "ESLAM_SUBREDDIT", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "type": "subredditBan", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + } + , + { + "_id": "639d098f025d17f64e8c0c1e2", + "subreddit": { + "_id": "639ce52b71990b53b75f4c7f", + "fixedName": "ESLAM_SUBREDDIT", + "name": "ESLAM_SUBREDDIT", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "type": "subredditMute", + "from": { + "_id": "638bed0c01f496d7284c281a3", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + } + , + { + "_id": "639d098f025d17f64e8c0c1e4", + "subreddit": { + "_id": "639ce52b71990b53b75f4c7f", + "fixedName": "ESLAM_SUBREDDIT", + "name": "ESLAM_SUBREDDIT", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "type": "subredditModeratorInvite", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + } + , + { + "_id": "639d098f025d17f64e8c0c1e5", + "subreddit": { + "_id": "639ce52b71990b53b75f4c7f", + "fixedName": "ESLAM_SUBREDDIT", + "name": "ESLAM_SUBREDDIT", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "type": "subredditModeratorRemove", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + } + , + { + "_id": "639d098f025d17f64e8c0c1e6", + "subreddit": { + "_id": "639ce52b71990b53b75f4c7f", + "fixedName": "ESLAM_SUBREDDIT", + "name": "ESLAM_SUBREDDIT", + "rules": [], + "icon": "http://localhost:8000/undefined", + "backgroundImage": "http://localhost:8000/undefined" + }, + "type": "subredditApprove", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Messi" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + },{ + "_id": "639d098f025d17f64e8c0c1e7", + "subject": { + "text": "Hello Eslam", + "_id": "639d098f025d17f64e81f" + }, + "text": "Can I call You?", + "type": "userMessage", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d8", + "userName": "Fady" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + }, + { + "_id": "639d098f025d17f64e8c0c1e9", + "subject": { + "text": "Hello Eslam", + "_id": "639d098f025d17f64e81f" + }, + "text": "Messi is hereeeeeee", + "type": "userMessage", + "from": { + "_id": "638bed0c01f496d7284c281a", + "userName": "Mohab" + }, + "to": { + "_id": "638bed0801f496d7284c280d", + "userName": "Esalm" + }, + "createdAt": "2022-12-17T00:12:50.498Z", + "isRead": false, + "isDeletedInSource": false, + "isDeletedInDestination": false + } + ] + +} \ No newline at end of file diff --git a/data/moderatorsList.json b/data/moderatorsList.json new file mode 100644 index 00000000..2b057f8c --- /dev/null +++ b/data/moderatorsList.json @@ -0,0 +1,53 @@ +{ + "status": "success", + "data": [ + { + "moderatorPermissions": { + "all": true, + "access": true, + "config": true, + "flair": true, + "posts": true + }, + "user": { + "_id": "0", + "userName": "fady", + "joinDate": "2019-08-24T14:15:22Z", + "profilePicture": "https://styles.redditmedia.com/t5_2ql2m/styles/communityIcon_vr02expkpl391.jpg?format=pjpg&s=6fc537d22ab75feda2ea15985e89da63c7564797" + }, + "_id": "63a16e536cdd7a6f4e7acdb2" + }, + { + "moderatorPermissions": { + "all": true, + "access": true, + "config": true, + "flair": true, + "posts": true + }, + "user": { + "_id": "0", + "userName": "adel", + "joinDate": "2019-08-24T14:15:22Z", + "profilePicture": "https://styles.redditmedia.com/t5_2ql2m/styles/communityIcon_vr02expkpl391.jpg?format=pjpg&s=6fc537d22ab75feda2ea15985e89da63c7564797" + }, + "_id": "63a16e536cdd7a6f4e7acdb2" + }, + { + "moderatorPermissions": { + "all": true, + "access": true, + "config": true, + "flair": true, + "posts": true + }, + "user": { + "_id": "0", + "userName": "hosny", + "joinDate": "2019-08-24T14:15:22Z", + "profilePicture": "https://styles.redditmedia.com/t5_2ql2m/styles/communityIcon_vr02expkpl391.jpg?format=pjpg&s=6fc537d22ab75feda2ea15985e89da63c7564797" + }, + "_id": "63a16e536cdd7a6f4e7acdb2" + } + ] +} \ No newline at end of file diff --git a/data/moreComments.json b/data/moreComments.json index 300ffab4..8d8ed593 100644 --- a/data/moreComments.json +++ b/data/moreComments.json @@ -1,72 +1,79 @@ { - "status": "string", + "status": "success", "comments": [ - { - "_id": "10", - "author": { - "_id": "639a5f0e995a7314c8c796c0", - "userName": "Aya Elhoseny", - "profilePicture": "https://styles.redditmedia.com/t5_74w4tr/styles/profileIcon_9or0sb8dtc5a1.jpeg?width=256&height=256&crop=256:256,smart&s=2a8b7dc794b00e51a6b9f423da2204a999136ecb", - "profileBackground": "users/defaultcover.png" - }, - "post": "string", - "mentions": [ - "string" - ], - "replies": [], - "parent": "string", - "parentType": "string", - "text": "Comment no 3 in the Post", - "createdAt": "2001-01-11T17:32:28Z", - "votes": 0, - "repliesCount": 0 - }, - { - "_id": "11", - "author": { - "_id": "639a5f0e998a7314c8c746c0", - "userName": "Youssef Elhoseny", - "profilePicture": "https://styles.redditmedia.com/t5_74w4tr/styles/profileIcon_9or0sb8dtc5a1.jpeg?width=256&height=256&crop=256:256,smart&s=2a8b7dc794b00e51a6b9f423da2204a999136ecb", - "profileBackground": "users/defaultcover.png" - }, - "post": "string", - "mentions": [ - "string" - ], - "replies": [], - "parent": "string", - "parentType": "string", - "text": "Comment no 4 in the Post", - "createdAt": "2022-12-13T17:32:28Z", - "votes": 0, - "repliesCount": 0 - }, - { - "_id": "12", - "author": { - "_id": "10", - "userName": "Basma Elhoseny", - "profilePicture": "https://styles.redditmedia.com/t5_74w4tr/styles/profileIcon_9or0sb8dtc5a1.jpeg?width=256&height=256&crop=256:256,smart&s=2a8b7dc794b00e51a6b9f423da2204a999136ecb", - "profileBackground": "users/defaultcover.png" - }, - "post": "string", - "mentions": [ - "string" - ], - "replies": [], - "parent": "string", - "parentType": "string", - "text": "Comment no 5 in the Post", - "createdAt": "2022-12-14T10:32:28Z", - "votes": 0, - "repliesCount": 0 - }, - { - "Type": "moreReplies", - "count": 90, - "children": [ - "string" - ] - } + { + "_id": "63a5618810ebdf1da11b5a0d", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [ + { + "_id": "63a5618f10ebdf1da11b5a23", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [ + { + "_id": "63a5619510ebdf1da11b5a39", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [], + "parent": "63a5618f10ebdf1da11b5a23", + "parentType": "Comment", + "text": "

Reply 10

", + "createdAt": "2022-12-23T08:06:45.791Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 0, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891402895.5, + "__v": 0 + } + ], + "parent": "63a5618810ebdf1da11b5a0d", + "parentType": "Comment", + "text": "

Reply 9

", + "createdAt": "2022-12-23T08:06:39.218Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 1, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891399609, + "__v": 0 + } + ], + "parent": "63a5618110ebdf1da11b59f7", + "parentType": "Comment", + "text": "

Reply 8

", + "createdAt": "2022-12-23T08:06:32.102Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 1, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891396051, + "__v": 0 + } ] } \ No newline at end of file diff --git a/data/morereplies.json b/data/morereplies.json new file mode 100644 index 00000000..17ca1b87 --- /dev/null +++ b/data/morereplies.json @@ -0,0 +1,77 @@ +{ + "status": "success", + "comments": [ + { + "_id": "63a560fa10ebdf1da11b58ac", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [], + "parent": "63a560de10ebdf1da11b581b", + "parentType": "Post", + "text": "

Comment 3

", + "createdAt": "2022-12-23T08:04:10.437Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 0, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891325218.5, + "__v": 0 + }, + { + "_id": "63a560f610ebdf1da11b5898", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [], + "parent": "63a560de10ebdf1da11b581b", + "parentType": "Post", + "text": "

Comment 2

", + "createdAt": "2022-12-23T08:04:06.694Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 0, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891323347, + "__v": 0 + }, + { + "_id": "63a560ed10ebdf1da11b5884", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [], + "parent": "63a560de10ebdf1da11b581b", + "parentType": "Post", + "text": "

Comment 1

", + "createdAt": "2022-12-23T08:03:57.303Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 0, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891318651.5, + "__v": 0 + } + ] +} \ No newline at end of file diff --git a/data/muteUnmuteList.json b/data/muteUnmuteList.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/data/muteUnmuteList.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/data/mutedList.json b/data/mutedList.json new file mode 100644 index 00000000..e592499f --- /dev/null +++ b/data/mutedList.json @@ -0,0 +1,119 @@ +{ + "status": "success", + "data": [ + { + "banInfo": { + "punishReason": "No reason", + "punish_type": "No Spoiler", + "Note": "he is bad person", + "duration": 20 + }, + "muteInfo": { + "muteMessage": "Spammer" + }, + "user": { + "_id": "63a107a3e72289e28e6b760d", + "userName": "Nour", + "joinDate": "2022-12-20T00:53:55.071Z", + "profilePicture": "users/default.png" + }, + "type": "banned", + "_id": "63a16ea36cdd7a6f4e7ace09" + }, + { + "banInfo": { + "punishReason": "No reason", + "punish_type": "No Spoiler", + "Note": "he is bad person", + "duration": 20 + }, + "muteInfo": { + "muteMessage": "Spammer" + }, + "user": { + "_id": "63a107a3e72289e28e6b760d", + "userName": "Nour", + "joinDate": "2022-12-20T00:53:55.071Z", + "profilePicture": "users/default.png" + }, + "type": "banned", + "_id": "63a16ea36cdd7a6f4e7ace09" + }, + { + "banInfo": { + "punishReason": "No reason", + "punish_type": "No Spoiler", + "Note": "he is bad person", + "duration": 20 + }, + "muteInfo": { + "muteMessage": "Spammer" + }, + "user": { + "_id": "63a107a3e72289e28e6b760d", + "userName": "Nour", + "joinDate": "2022-12-20T00:53:55.071Z", + "profilePicture": "users/default.png" + }, + "type": "banned", + "_id": "63a16ea36cdd7a6f4e7ace09" + }, + { + "banInfo": { + "punishReason": "No reason", + "punish_type": "No Spoiler", + "Note": "he is bad person", + "duration": 20 + }, + "muteInfo": { + "muteMessage": "Spammer" + }, + "user": { + "_id": "63a107a3e72289e28e6b760d", + "userName": "Nour", + "joinDate": "2022-12-20T00:53:55.071Z", + "profilePicture": "users/default.png" + }, + "type": "muted", + "_id": "63a16ea36cdd7a6f4e7ace09" + }, + { + "banInfo": { + "punishReason": "No reason", + "punish_type": "No Spoiler", + "Note": "he is bad person", + "duration": 20 + }, + "muteInfo": { + "muteMessage": "Spammer" + }, + "user": { + "_id": "63a107a3e72289e28e6b760d", + "userName": "Nour", + "joinDate": "2022-12-20T00:53:55.071Z", + "profilePicture": "users/default.png" + }, + "type": "muted", + "_id": "63a16ea36cdd7a6f4e7ace09" + }, + { + "banInfo": { + "punishReason": "No reason", + "punish_type": "No Spoiler", + "Note": "he is bad person", + "duration": 20 + }, + "muteInfo": { + "muteMessage": "Spammer" + }, + "user": { + "_id": "63a107a3e72289e28e6b760d", + "userName": "Nour", + "joinDate": "2022-12-20T00:53:55.071Z", + "profilePicture": "users/default.png" + }, + "type": "muted", + "_id": "63a16ea36cdd7a6f4e7ace09" + } + ] +} \ No newline at end of file diff --git a/data/notificationToken.json b/data/notificationToken.json index 9e26dfee..f1981f19 100644 --- a/data/notificationToken.json +++ b/data/notificationToken.json @@ -1 +1,3 @@ -{} \ No newline at end of file +{ +"status": "success" +} \ No newline at end of file diff --git a/data/overview.json b/data/overview.json index f6ed88fd..5ccf989d 100644 --- a/data/overview.json +++ b/data/overview.json @@ -41,6 +41,7 @@ "sortOnHot": 0 }, { + "_id": "198725", "author": { "_id": "string", "name": "NourZiad122" @@ -121,6 +122,7 @@ "sortOnHot": 9 }, { + "_id": "198725", "author": { "_id": "string", "name": "NourZiad122" @@ -161,6 +163,7 @@ "sortOnHot": 80 }, { + "_id": "198725", "author": { "_id": "string", "name": "NourZiad122" diff --git a/data/postcomments.json b/data/postcomments.json index 571cc7f0..12ac7a90 100644 --- a/data/postcomments.json +++ b/data/postcomments.json @@ -1,109 +1,334 @@ { - "status": "string", - "comments": [ - { - "_id": "1", - "author": { - "_id": "10", - "userName": "Basma Elhoseny", - "profilePicture": "https://styles.redditmedia.com/t5_74w4tr/styles/profileIcon_9or0sb8dtc5a1.jpeg?width=256&height=256&crop=256:256,smart&s=2a8b7dc794b00e51a6b9f423da2204a999136ecb", - "profileBackground": "users/defaultcover.png" + "status": "success", + "comments": [ + { + "_id": "63a5613e10ebdf1da11b592e", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [], + "parent": "63a560de10ebdf1da11b581b", + "parentType": "Post", + "text": "

Comment 7

", + "createdAt": "2022-12-23T08:05:18.865Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 0, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891359432.5, + "__v": 0 }, - "post": "string", - "mentions": [ - "string" - ], - "replies": [ - { - "_id": "101", - "author": { - "_id": "639a5f0e995a7314c8c746c8", - "userName": "Eslam", - "profilePicture": "https://styles.redditmedia.com/t5_74w4tr/styles/profileIcon_9or0sb8dtc5a1.jpeg?width=256&height=256&crop=256:256,smart&s=2a8b7dc794b00e51a6b9f423da2204a999136ecb", - "profileBackground": "users/defaultcover.png" - }, - "post": "string", - "mentions": [ - "string" - ], - "replies": [ - { - "_id": "10101", - "author": { - "_id": "639a5f0e995a7314c8c746c5", - "userName": "Eslam", - "profilePicture": "https://styles.redditmedia.com/t5_74w4tr/styles/profileIcon_9or0sb8dtc5a1.jpeg?width=256&height=256&crop=256:256,smart&s=2a8b7dc794b00e51a6b9f423da2204a999136ecb", - "profileBackground": "users/defaultcover.png" + { + "_id": "63a5613b10ebdf1da11b591a", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [ + { + "_id": "63a5615810ebdf1da11b5973", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" }, - "post": "string", - "mentions": [ - "string" - ], - "replies": [ - "150", - "160", - "180" - ], - "parent": "string", - "parentType": "string", - "text": "Level 3 Eslam's Comment", - "createdAt": "2017-07-21T17:32:28Z", - "votes": 0, - "repliesCount": 0 - }, - { - "Type": "moreReplies", - "count": 0, - "children": [ - "10", - "11", - "12" - ] - } - ], - "parent": "string", - "parentType": "string", - "text": "Reply on Comment 1", - "createdAt": "2017-07-21T17:32:28Z", - "votes": 0, - "repliesCount": 0 - } - ], - "parent": "string", - "parentType": "string", - "text": "Basma's Comment", - "createdAt": "2017-07-21T17:32:28Z", - "votes": 0, - "repliesCount": 0 - }, - { - "_id": "2", - "author": { - "_id": "639a5f0e995a7314c8c746a5", - "userName": "Eslam", - "profilePicture": "https://styles.redditmedia.com/t5_74w4tr/styles/profileIcon_9or0sb8dtc5a1.jpeg?width=256&height=256&crop=256:256,smart&s=2a8b7dc794b00e51a6b9f423da2204a999136ecb", - "profileBackground": "users/defaultcover.png" - }, - "post": "string", - "mentions": [ - "string" - ], - "replies": [], - "parent": "string", - "parentType": "string", - "text": "Eslam's Comment", - "createdAt": "2017-07-21T17:32:28Z", - "votes": 0, - "repliesCount": 0 - }, - { - "Type": "moreReplies", - "count": 100, - "children": [ - "10", - "11", - "12" - ] - } - ] -} \ No newline at end of file + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [ + { + "_id": "63a5615e10ebdf1da11b5989", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [ + { + "_id": "63a5616510ebdf1da11b599f", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [ + { + "_id": "63a5616b10ebdf1da11b59b5", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [ + { + "_id": "63a5617210ebdf1da11b59cb", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [ + { + "_id": "63a5617a10ebdf1da11b59e1", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [ + { + "_id": "63a5618110ebdf1da11b59f7", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [ + { + "_id": "63a5618810ebdf1da11b5a0d", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [ + "63a5618f10ebdf1da11b5a23" + ], + "parent": "63a5618110ebdf1da11b59f7", + "parentType": "Comment", + "text": "

Reply 8

", + "createdAt": "2022-12-23T08:06:32.102Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 1, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891396051, + "__v": 0 + } + ], + "parent": "63a5617a10ebdf1da11b59e1", + "parentType": "Comment", + "text": "

Reply 7

", + "createdAt": "2022-12-23T08:06:25.400Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 1, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891392700, + "__v": 0 + } + ], + "parent": "63a5617210ebdf1da11b59cb", + "parentType": "Comment", + "text": "

Reply 6

", + "createdAt": "2022-12-23T08:06:18.659Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 1, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891389329.5, + "__v": 0 + } + ], + "parent": "63a5616b10ebdf1da11b59b5", + "parentType": "Comment", + "text": "

Reply 5

", + "createdAt": "2022-12-23T08:06:10.949Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 1, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891385474.5, + "__v": 0 + } + ], + "parent": "63a5616510ebdf1da11b599f", + "parentType": "Comment", + "text": "

Reply 4

", + "createdAt": "2022-12-23T08:06:03.391Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 1, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891381695.5, + "__v": 0 + } + ], + "parent": "63a5615e10ebdf1da11b5989", + "parentType": "Comment", + "text": "

Reply 3

", + "createdAt": "2022-12-23T08:05:57.133Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 1, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891378566.5, + "__v": 0 + } + ], + "parent": "63a5615810ebdf1da11b5973", + "parentType": "Comment", + "text": "

Reply 2

", + "createdAt": "2022-12-23T08:05:50.118Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 1, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891375059, + "__v": 0 + } + ], + "parent": "63a5613b10ebdf1da11b591a", + "parentType": "Comment", + "text": "

Reply 1

", + "createdAt": "2022-12-23T08:05:44.550Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 1, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891372275, + "__v": 0 + } + ], + "parent": "63a560de10ebdf1da11b581b", + "parentType": "Post", + "text": "

Comment 6

", + "createdAt": "2022-12-23T08:05:15.576Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 1, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891357788, + "__v": 0 + }, + { + "_id": "63a5613510ebdf1da11b5906", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [], + "parent": "63a560de10ebdf1da11b581b", + "parentType": "Post", + "text": "

Comment 5

", + "createdAt": "2022-12-23T08:05:09.581Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 0, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891354790.5, + "__v": 0 + }, + { + "_id": "63a5613110ebdf1da11b58f2", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [], + "parent": "63a560de10ebdf1da11b581b", + "parentType": "Post", + "text": "

Comment 4

", + "createdAt": "2022-12-23T08:05:05.132Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 0, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891352566, + "__v": 0 + }, + { + "_id": "63a560fa10ebdf1da11b58ac", + "author": { + "_id": "63a2174cbe566ac6458d2c1c", + "userName": "Basma", + "profilePicture": "https://api.nonlegit.click/users/Basma/user-Basma-1671568902238.jpeg", + "profileBackground": "https://api.nonlegit.click/users/defaultcover.png", + "displayName": "Basma Elhoseny" + }, + "post": "63a560de10ebdf1da11b581b", + "mentions": [], + "replies": [], + "parent": "63a560de10ebdf1da11b581b", + "parentType": "Post", + "text": "

Comment 3

", + "createdAt": "2022-12-23T08:04:10.437Z", + "isDeleted": false, + "votes": 0, + "repliesCount": 0, + "locked": false, + "modState": "unmoderated", + "sortOnHot": 835891325218.5, + "__v": 0 + }, + { + "Type": "moreReplies", + "count": 2, + "children": [ + "string" + ] + } + ] + } \ No newline at end of file diff --git a/data/routes.json b/data/routes.json index bca83a7e..4823ba1e 100644 --- a/data/routes.json +++ b/data/routes.json @@ -1,17 +1,26 @@ { + + "/users/followers?limit=:limit&page=:page": "/followers", + "/users/upvoted?limit=:limit&page=:page": "/upvoted", + "/users/downvoted?limit=:limit&page=:page": "/downvoted", + "/users/saved?limit=:limit&page=:page": "/saved", + "/users/hidden?limit=:limit&page=:page": "/hidden", + "/users/username_available?userName=*": "/usernameAvailable", - "/users/:name/overview?limit=:limit&page=:page&sort=:sortType": "/overview", - "/users/:name/posts?limit=:limit&page=:page&sort=:sortType": "/postsTap", - "/users/:name/comments?limit=:limit&page=:page&sort=:sortType": "/commentsTap", - "/users/followers?limit=:limit&page=:page":"/followers", - "/subreddits/random/leaderboard?limit=4&page=0":"/homePageCommunities", - "/subreddits/:subredditName/about/posts/:location?limit=:limit&page=:page&sort=:sortType":"/modQueue", - "/subreddits/:name/": "/Subreddit", - "/subreddits": "/CreatSubreddit", - "/subreddits/:subredditName/:name/hot?limit=:limit&page=:page": "/hot", - "/subreddits/:Name/subscribe": "/join", - "/subreddits/:Name/top?limit=:limit&page=:page": "/top", - "/subreddits/:Name/new?limit=:limit&page=:page": "/new", + "/users/me/prefs": "/settings", + "/users/upvoted": "/upvoted", + "/users/downvoted": "/downvoted", + "/users/saved": "/saved", + "/users/hidden": "/hidden", + "/users/new": "/new", + "/users/hot": "/hot", + "/users/top": "/top", + "/users/best": "/best", + "/users/logout": "/logout", + "/users/social_links": "/socialLinks", + "/users/image": "/userImage", + "/users/blocked": "/listBlock", + "/users/followers": "/followers", "/users/signup": "/signup", "/users/username_available?userName=:username": "/unique", "/users/me/": "/me", @@ -23,59 +32,124 @@ "/users/forgot_username": "/forgetusername", "/users/reset_password/:token": "/resetpassword", "/users/notifications": "/notifications", - "/users/me/prefs": "/settings", - "/subreddits/mine/moderator": "/subreddits", - "/subreddits/moderator/:name": "/userSubreddits", - "/users/:name/overview?sort=:sortType&limit=:limit&page=:page": "/overview", - "/users/:name/posts?sort=:sortType&limit=:limit&page=:page": "/postsTap", - "/users/:name/comments?sort=:sortType&limit=:limit&page=:page": "/commentsTap", - "/users/upvoted?limit=:limit&page=:page": "/upvoted", - "/users/downvoted?limit=:limit&page=:page": "/downvoted", - "/users/saved?limit=:limit&page=:page": "/saved", - "/users/hidden?limit=:limit&page=:page": "/hidden", - "/subreddits/mine/subscriber": "/subredditsHomePage", "/users/new?limit=:limit&page=:page": "/new", "/users/hot?limit=:limit&page=:page": "/hot", "/users/top?limit=:limit&page=:page": "/top", "/users/best?limit=:limit&page=:page": "/best", - "/users/username_available?userName=*": "/usernameAvailable", - "/users/logout": "/logout", + "/users/change_email": "/changePassword", + "/users/change_password": "/changeEmail", + "/users/delete_account/": "/deleteAccount", + "/users/check_reset_token/:token": "/token", - "/users/:Name/about/": "/userInfo", - "/users/social_links": "/socialLinks", "/users/social_links/:id": "/postSocialLinks", - "/users/image": "/userImage", - "/users/blocked": "/listBlock", "/users/notifications/:notificationId/mark_as_read": "/markAsRead", - "/users/notifications/mark_as_read": "/markAsRead", "/users/notifications/:notificationId/hide": "/hideNotification", + "/users/notifications/mark_as_read": "/markAsRead", + + "/users/verify_email/:token": "/verifyEmail", + + "/users/:name/overview?limit=:limit&page=:page&sort=:sortType": "/overview", + "/users/:name/comments?sort=:sortType&limit=:limit&page=:page": "/commentsTap", + "/users/:name/comments/:something": "/commentsTap", + "/users/:name/comments": "/commentsTap", + + "/users/:name/overview?sort=:sortType&limit=:limit&page=:page": "/overview", + "/users/:name/overview": "/overview", + + "/users/:name/posts?limit=:limit&page=:page&sort=:sortType": "/postsTap", + "/users/:name/posts?sort=:sortType&limit=:limit&page=:page": "/postsTap", + "/users/:name/posts/:something": "/postsTap", + "/users/:name/posts": "/postsTap", + + "/users/:Name/about/": "/userInfo", "/users/:name/follow": "/follow", "/users/:name/unfollow": "/follow", "/users/:name/block_user": "/block", "/users/:name/unblock_user": "/block", - "/users/followers": "/followers", - "/posts/:postId/:action": "/postAction", - "/posts/:postId": "/deleteAction", - "/posts/:postId/actions/:action": "/actionOnPost", - "/subreddits/:subreddit/flair": "/subredditFlairs", - "/getpost/:postID": "/getpost", - "/posts/:postID": "/editpost", + + "/comments": "/createcomment", + "/comments/comment_tree/:postID?limit=:limit&depth=:depth&sort=:sort&commentId:commentId": "/morecomments", + "/comments/comment_tree/:postID?limit=:limit&depth=:depth&sort=:sort": "/postcomments", "/comments/comment_tree/:postID": "/postcomments", + "/comments/more_children?children=:children&depth=:depth": "/morereplies", "/comments/more_children": "/morecomments", + "/comments/:commentId": "/editcomment", + "/comments/:commentID/save": "/savecomment", "/comments/:id/:action": "/commentMod", "/comments/:id/moderate/:action": "/commentMod", + + "/posts/:postID": "/getpost", + "/posts/:postId/actions/:action": "/actionOnPost", + "/posts/:postId/moderate/:action": "/moderatorAction", "/posts/:postId/save": "/save", "/posts/:postId/unsave": "/unsave", "/posts/:postId/hide": "/hide", - "/posts/:postId/delete": "/delete", "/posts/:postId/unhide": "/hide", "/posts/:postId/vote": "/vote", "/posts/:postId/images": "/addImagesToPost", - "/posts/:postId/moderate/:action": "/moderatorAction", - "/t/:name/":"/exploreCommunities", - "subreddits/:Name/flairs/:id": "/UpdateFlair", + "/posts/:postId/delete": "/delete", + "/posts/:postId/:action": "/postAction", + "/posts/:postId":"/deleteAction", + + "/t/:name/": "/exploreCommunities", + + "/messages": "/MessageDrive", + "/messages/sent": "/messageSent", + "/messages/post_replies": "/MessagePostReplay", + "/messages/all": "/messagesAll", + "/messages/unread": "/messageUnread", + "/messages/mark_as_read": "/messageAsRead", + "/messages/:parentMessageId/reply": "/MessageReplay", + "/messages/:messageId": "/messageRemove", + "/notifications/token": "/notificationToken", - "/subreddits/:subredditName/banned": "/baned", - "/subreddits/leaderboard/:category?limit=:limit&page=:page": "/TopCommunities" -} + + "/getpost/:postID": "/getpost", + + "/subreddits": "/CreatSubreddit", + "/subreddits/random/leaderboard?limit=4&page=0": "/homePageCommunities", + "/subreddits/mine/moderator": "/subreddits", + "/subreddits/mine/subscriber": "/subredditsHomePage", + "/subreddits/moderator/:name": "/userSubreddits", + "/subreddits/leaderboard/:category?limit=:limit&page=:page": "/TopCommunities", + + "/subreddits/:Name/subscribe": "/join", + "/subreddits/:Name/top": "/top", + "/subreddits/:Name/new": "/new", + "/subreddits/:subreddit/flair": "/subredditFlairs", + "/subreddits/:subredditName/muted": "/muted", + "/subreddits/:subredditName/moderators": "/moderators", + "/subreddits/:subredditName/approved_users": "/approved", + + "/subreddits/:subredditName/invited_moderators": "/invitedModerators", + "/subreddits/:subredditName/moderators/:moderatorName": "/edit", + "/subreddits/:subredditName/mute_settings/:action/:userName": "/muteUnmute", + "/subreddits/:subredditName/approve_settings/:action/:userName": "/approvedUnapproved", + "/subreddits/:subredditName/Ban_settings/:action/:userName": "/banUnban", + "/subreddits/:subredditName/banned": "/banned", + "/subreddits/:subredditName/flairs": "/AddFlair", + "/subreddits/:subredditName/flairs/:flairId": "/EditFlair", + "/subreddits/:subredditName/rules/:title": "/AddRule", + "/subreddits/:subReddit/moderators/:userName": "/invite", + + "/subreddits/:subredditName/about/posts/:location?limit=:limit&page=:page&sort=:sortType": "/modQueue", + + "/subreddits/:Name/top?limit=:limit&page=:page": "/top", + "/subreddits/:Name/new?limit=:limit&page=:page": "/new", + + "/subreddits/:subredditName/:name/hot?limit=:limit&page=:page": "/hot", + "/subreddits/:subredditName/:name/hot": "/hot", + "/subreddits/:subredditName/:action/invitation": "/SubreddtInvitation", + + "/subreddits/:subredditName/:userName/:action/approve_user": "/approvedUnapproved", + "/subreddits/:name/": "/Subreddit", + "/subreddits/:Name/flairs/:id": "/UpdateFlair", + + + + "/search?limit=6&page=0&type=people&sort=:new&time=:day&q=:ahmed": "/SearchByPeople", + "/search?limit=6&page=0&type=communities&sort=:new&time=:day&q=:ahmed": "/SearchByCommunity", + "/search?limit=6&page=0&type=posts&sort=:new&time=:day&q=:ahmed": "/SearchByPost", + "/search?limit=6&page=0&type=comments&sort=:new&time=:day&q=:ahmed": "/SearchByComments" + } \ No newline at end of file diff --git a/data/savecomment.json b/data/savecomment.json new file mode 100644 index 00000000..0460d167 --- /dev/null +++ b/data/savecomment.json @@ -0,0 +1,3 @@ +{ + "status": "success" +} \ No newline at end of file diff --git a/data/submitPost.json b/data/submitPost.json index eb5c262a..5c456d96 100644 --- a/data/submitPost.json +++ b/data/submitPost.json @@ -1,26 +1,28 @@ -[ - { - "{\"title\":\"jxbhjx\",\"text\":\"jxbjh\",\"kind\":\"text\",\"owner\":0,\"ownerType\":\"Subreddit\",\"spoiler\":false,\"nswf\":false,\"sendReplies\":true}": "", - "id": 1 - }, - { - "{\"title\":\"Wa2fet nasyet zaman\",\"text\":\"\\n\",\"kind\":\"text\",\"owner\":0,\"ownerType\":\"Subreddit\",\"spoiler\":false,\"nswf\":false,\"sendReplies\":true}": "", - "id": 2 - }, - { - "{\"title\":\"Oh ya\",\"text\":\"\\n\",\"kind\":\"text\",\"owner\":0,\"ownerType\":\"Subreddit\",\"spoiler\":true,\"nswf\":true,\"sendReplies\":true}": "", - "id": 3 - }, - { - "{\"title\":\"Oh ya\",\"text\":\"lorem\\n\",\"kind\":\"text\",\"owner\":0,\"ownerType\":\"Subreddit\",\"spoiler\":true,\"nswf\":true,\"sendReplies\":false}": "", - "id": 4 - }, - { - "{\"title\":\"hd\",\"kind\":\"text\",\"owner\":2,\"ownerType\":\"Subreddit\",\"spoiler\":false,\"nswf\":false,\"sendReplies\":true}": "", - "id": 5 - }, - { - "{\"title\":\"hd\",\"kind\":\"text\",\"owner\":3,\"ownerType\":\"Subreddit\",\"spoiler\":false,\"nswf\":false,\"sendReplies\":true}": "", - "id": 6 - } -] +{ + "posts": [ + { + "{\"title\":\"jxbhjx\",\"text\":\"jxbjh\",\"kind\":\"text\",\"owner\":0,\"ownerType\":\"Subreddit\",\"spoiler\":false,\"nswf\":false,\"sendReplies\":true}": "", + "id": 1 + }, + { + "{\"title\":\"Wa2fet nasyet zaman\",\"text\":\"\\n\",\"kind\":\"text\",\"owner\":0,\"ownerType\":\"Subreddit\",\"spoiler\":false,\"nswf\":false,\"sendReplies\":true}": "", + "id": 2 + }, + { + "{\"title\":\"Oh ya\",\"text\":\"\\n\",\"kind\":\"text\",\"owner\":0,\"ownerType\":\"Subreddit\",\"spoiler\":true,\"nswf\":true,\"sendReplies\":true}": "", + "id": 3 + }, + { + "{\"title\":\"Oh ya\",\"text\":\"lorem\\n\",\"kind\":\"text\",\"owner\":0,\"ownerType\":\"Subreddit\",\"spoiler\":true,\"nswf\":true,\"sendReplies\":false}": "", + "id": 4 + }, + { + "{\"title\":\"hd\",\"kind\":\"text\",\"owner\":2,\"ownerType\":\"Subreddit\",\"spoiler\":false,\"nswf\":false,\"sendReplies\":true}": "", + "id": 5 + }, + { + "{\"title\":\"hd\",\"kind\":\"text\",\"owner\":3,\"ownerType\":\"Subreddit\",\"spoiler\":false,\"nswf\":false,\"sendReplies\":true}": "", + "id": 6 + } + ] +} diff --git a/data/verifyEmail.json b/data/verifyEmail.json new file mode 100644 index 00000000..f1981f19 --- /dev/null +++ b/data/verifyEmail.json @@ -0,0 +1,3 @@ +{ +"status": "success" +} \ No newline at end of file diff --git a/devops/jenkins/Jenkinsfile b/devops/jenkins/Jenkinsfile index 4397af88..0d9f6451 100644 --- a/devops/jenkins/Jenkinsfile +++ b/devops/jenkins/Jenkinsfile @@ -11,54 +11,20 @@ pipeline { FACEBOOK_APP_ID = credentials('facebook-app-id') GOOGLE_APP_ID = credentials('google-app-id') REACT_APP_SITEKEY = credentials('react-app-sitekey') - + AWS_ACCESS_KEY_ID = credentials('aws-access-key-id') + AWS_SECRET_ACCESS_KEY = credentials('aws-secret-access-key') } steps { - sh ''' - # Set up git credentials. - if [ ! -f "/var/jenkins_home/git-askpass-helper.sh" ]; then - echo "#!/bin/bash" >> /var/jenkins_home/git-askpass-helper.sh - echo 'exec echo $GIT_PASSWORD' >> /var/jenkins_home/git-askpass-helper.sh - chmod +x /var/jenkins_home/git-askpass-helper.sh - fi - export GIT_ASKPASS=/var/jenkins_home/git-askpass-helper.sh - # Getting the backend docker files - mkdir temp; cd temp - git clone https://cynico@github.com/NonLegit/devops.git - cp devops/dockerfiles/frontend/Dockerfile .. - cd .. ; rm -rf temp - # Cleaning unnecessary files. - rm -f README* .gitignore - # Creating the necessary files. - echo 'HTTP=false -PORT=443 -HOST=0.0.0.0 -REACT_APP_GOOGLECLIENTID=\'"$GOOGLE_APP_ID"\' -REACT_APP_FACEBOOKCLIENTID=\'"$FACEBOOK_APP_ID"\' -REACT_APP_SITEKEY="6LdjH-kiAAAAANFbV6SUnCjXNK3Z0h7q7j4IFf7i" -REACT_APP_ENV='production' -REACT_APP_PROXY_DEVELOPMENT="http://localhost:8000" -REACT_APP_PROXY_PRODUCTION="https://api.nonlegit.click/api/v1"' > .env - # Build the docker image - docker build -t cynic0/reddit-frontend:latest . - # Push the docker image. - # docker login --username $DOCKER_CREDS_USR --password $DOCKER_CREDS_PSW - # docker push cynic0/reddit-frontend:latest - # Deleting credentials file from filesystem. - rm -f /var/jenkins_home/.docker/config.json - ''' - } + sh(returnStdout: true, script: "bash -e /var/jenkins_home/scripts/frontend/build.sh") + } } stage('Deploying frontend') { when { branch "main" } steps { - sh ''' - docker rm -f frontend - docker run --name=frontend --network backend_backend --ip 10.0.1.4 --restart always -d cynic0/reddit-frontend:latest - ''' + sh(returnStdout: true, script: "bash -e /var/jenkins_home/scripts/frontend/deploy.sh") } } } -} \ No newline at end of file +} diff --git a/docs/About.html b/docs/About.html new file mode 100644 index 00000000..f8494442 --- /dev/null +++ b/docs/About.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: About + + + + + + + + + + +
+ +

Class: About

+ + + + + + +
+ +
+ +

About() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new About() → {React.Component}

+ + + + + + +
+

About Section for normal user

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • About Section for normal user
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/AccountPreferences.html b/docs/AccountPreferences.html new file mode 100644 index 00000000..bb4165a9 --- /dev/null +++ b/docs/AccountPreferences.html @@ -0,0 +1,173 @@ + + + + + JSDoc: Class: AccountPreferences + + + + + + + + + + +
+ +

Class: AccountPreferences

+ + + + + + +
+ +
+ +

AccountPreferences()

+ + +
+ + + +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/AddBtn.html b/docs/AddBtn.html new file mode 100644 index 00000000..9b30b607 --- /dev/null +++ b/docs/AddBtn.html @@ -0,0 +1,571 @@ + + + + + JSDoc: Class: AddBtn + + + + + + + + + + +
+ +

Class: AddBtn

+ + + + + + +
+ +
+ +

AddBtn(tempString) → {React.Component}

+ + +
+ +
+
+ + + + + + +

new AddBtn(tempString) → {React.Component}

+ + + + + + +
+

AddButton(community topics)

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
tempString + + +string + + + +

list of topics

+ + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
removeItem + + +function + + + +

remove ele from list of topics

handleChange + + +function + + + +

remove ele from list of topics

trueShawList + + +function + + + +

shoe list of topics

handleKeyDown + + +function + + + +

add ele to list of topics

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • AddButton(community topics)
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

AddBtn() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new AddBtn() → {React.Component}

+ + + + + + +
+

Add item to list of topics

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
SaveAction + + +function + + + +

save new data and send to backend

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Add item to list of topics
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/AddList.html b/docs/AddList.html new file mode 100644 index 00000000..723bbd36 --- /dev/null +++ b/docs/AddList.html @@ -0,0 +1,775 @@ + + + + + JSDoc: Class: AddList + + + + + + + + + + +
+ +

Class: AddList

+ + + + + + +
+ +
+ +

AddList() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new AddList() → {React.Component}

+ + + + + + +
+

AddList(community topics)

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleKeyDown + + +function + + + +

handel on press enter to add the community topic

removeItem + + +function + + + +

to remove element from list of topics

ListSelected + + +function + + + +

add item when select from list

trueShawList + + +function + + + +

show list

handleClickAway + + +function + + + +

close list a

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • AddList(community topics)
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

AddList() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new AddList() → {React.Component}

+ + + + + + +
+

AddList(community topics)

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleKeyDown + + +function + + + +

handel on press enter to add the community topic

removeItem + + +function + + + +

to rempve element when press x

ListSelected + + +function + + + +

add item when select from list

trueShaw + + +function + + + +

open the input

falseShaw + + +function + + + +

clase the input

trueShawList + + +function + + + +

open the list ip topics

setTemp + + +function + + + +

set new list of topics

setTag + + +function + + + +

set new list of topics

sendData + + +function + + + +

send data to backend

handleClickAway1 + + +function + + + +

return to default view of add list

decord + + +function + + + +

descord all changes

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • AddList(community topics)
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/AddSector.html b/docs/AddSector.html new file mode 100644 index 00000000..409a58d0 --- /dev/null +++ b/docs/AddSector.html @@ -0,0 +1,361 @@ + + + + + JSDoc: Class: AddSector + + + + + + + + + + +
+ +

Class: AddSector

+ + + + + + +
+ +
+ +

AddSector() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new AddSector() → {React.Component}

+ + + + + + +
+

Add discreption for the community

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClickAway1 + + +function + + + +

return to defult mode when click away

handleChange + + +function + + + +

count number of char in input feild to make sure not exeed the limit

falseShow + + +function + + + +

close the input

sendData + + +function + + + +

send data to backend

SaveAction + + +function + + + +

save all data and send to backend

decord + + +function + + + +

descord all changes in input

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Add discreption for the community
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/AllContainer.html b/docs/AllContainer.html new file mode 100644 index 00000000..0e0d5154 --- /dev/null +++ b/docs/AllContainer.html @@ -0,0 +1,193 @@ + + + + + JSDoc: Class: AllContainer + + + + + + + + + + +
+ +

Class: AllContainer

+ + + + + + +
+ +
+ +

AllContainer() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new AllContainer() → {React.Component}

+ + + + + + +
+

This component works as a container for all popular page components +and a repository the data fetched in

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Container represents the popular page

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Approve.html b/docs/Approve.html new file mode 100644 index 00000000..1d1d160a --- /dev/null +++ b/docs/Approve.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: Approve + + + + + + + + + + +
+ +

Class: Approve

+ + + + + + +
+ +
+ +

Approve() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Approve() → {React.Component}

+ + + + + + +
+

the whole page of approved

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • approved user page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ApprovePopUp.html b/docs/ApprovePopUp.html new file mode 100644 index 00000000..f103fb93 --- /dev/null +++ b/docs/ApprovePopUp.html @@ -0,0 +1,190 @@ + + + + + JSDoc: Class: ApprovePopUp + + + + + + + + + + +
+ +

Class: ApprovePopUp

+ + + + + + +
+ +
+ +

ApprovePopUp() → {React.Component}

+ + +
+ + + +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ApprovedUser.html b/docs/ApprovedUser.html new file mode 100644 index 00000000..42933dd9 --- /dev/null +++ b/docs/ApprovedUser.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Class: ApprovedUser + + + + + + + + + + +
+ +

Class: ApprovedUser

+ + + + + + +
+ +
+ +

ApprovedUser() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ApprovedUser() → {React.Component}

+ + + + + + +
+

approved user instance

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
userName + + +string + + + +

username of the approved user

profilePicture + + +string + + + +

link to the profile picture of the approved

joiningDate + + +string + + + +

the date of the approved user to be approved

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • approved user instance
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ApprovedUserList.html b/docs/ApprovedUserList.html new file mode 100644 index 00000000..a8bda261 --- /dev/null +++ b/docs/ApprovedUserList.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: ApprovedUserList + + + + + + + + + + +
+ +

Class: ApprovedUserList

+ + + + + + +
+ +
+ +

ApprovedUserList() → {React.Component}

+ + +
+ + + +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Aprrove.html b/docs/Aprrove.html new file mode 100644 index 00000000..24d0bba2 --- /dev/null +++ b/docs/Aprrove.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: Aprrove + + + + + + + + + + +
+ +

Class: Aprrove

+ + + + + + +
+ +
+ +

Aprrove() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Aprrove() → {React.Component}

+ + + + + + +
+

the whole page of approved

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • approved user page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ArrowList.html b/docs/ArrowList.html new file mode 100644 index 00000000..40399bfa --- /dev/null +++ b/docs/ArrowList.html @@ -0,0 +1,267 @@ + + + + + JSDoc: Class: ArrowList + + + + + + + + + + +
+ +

Class: ArrowList

+ + + + + + +
+ +
+ +

ArrowList() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ArrowList() → {React.Component}

+ + + + + + +
+

the upvoted and downvoted arrows in responsive postfooter

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
points + + +number + + + +

get number of upvotes or downvotes on a post

postVoteStatus + + +number + + + +

get if the post is upvoted or downvoted or none

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

ArrowList

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/BackHomeBottun.html b/docs/BackHomeBottun.html new file mode 100644 index 00000000..0d564f37 --- /dev/null +++ b/docs/BackHomeBottun.html @@ -0,0 +1,180 @@ + + + + + JSDoc: Class: BackHomeBottun + + + + + + + + + + +
+ +

Class: BackHomeBottun

+ + + + + + +
+ +
+ +

BackHomeBottun()

+ + +
+ +
+
+ + + + + + +

new BackHomeBottun()

+ + + + + + +
+

function to handle in click back to to of page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

top of the page

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/BackToTop.html b/docs/BackToTop.html new file mode 100644 index 00000000..fb1e92e0 --- /dev/null +++ b/docs/BackToTop.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: BackToTop + + + + + + + + + + +
+ +

Class: BackToTop

+ + + + + + +
+ +
+ +

BackToTop() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new BackToTop() → {React.Component}

+ + + + + + +
+

This component is the back to top button

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

back to top button

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Ban.html b/docs/Ban.html new file mode 100644 index 00000000..e0191945 --- /dev/null +++ b/docs/Ban.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: Ban + + + + + + + + + + +
+ +

Class: Ban

+ + + + + + +
+ +
+ +

Ban() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Ban() → {React.Component}

+ + + + + + +
+

the whole page of banned

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • banned user page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/BanFooter.html b/docs/BanFooter.html new file mode 100644 index 00000000..1d57852d --- /dev/null +++ b/docs/BanFooter.html @@ -0,0 +1,269 @@ + + + + + JSDoc: Class: BanFooter + + + + + + + + + + +
+ +

Class: BanFooter

+ + + + + + +
+ +
+ +

BanFooter() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new BanFooter() → {React.Component}

+ + + + + + +
+

Ban Footer

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClickCloseBan + + +function + + + +

close the popup when a button is clicked

handleBan + + +function + + + +

operate the function of banning user and send data to backend when a button is clicked

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Ban Footer component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/BanMessage.html b/docs/BanMessage.html new file mode 100644 index 00000000..93a9f791 --- /dev/null +++ b/docs/BanMessage.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: BanMessage + + + + + + + + + + +
+ +

Class: BanMessage

+ + + + + + +
+ +
+ +

BanMessage() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new BanMessage() → {React.Component}

+ + + + + + +
+

BanMessage

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
punishReason + + +string + + + +

text to explain more details about why this user is banned if available

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • BanMessageComponent (text area)
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/BanNote.html b/docs/BanNote.html new file mode 100644 index 00000000..e04aca55 --- /dev/null +++ b/docs/BanNote.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: BanNote + + + + + + + + + + +
+ +

Class: BanNote

+ + + + + + +
+ +
+ +

BanNote() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new BanNote() → {React.Component}

+ + + + + + +
+

BanNote

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
note + + +string + + + +

a note from the moderator about the banned user

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Bannote (text field)
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/BanPeriod.html b/docs/BanPeriod.html new file mode 100644 index 00000000..5dcffe20 --- /dev/null +++ b/docs/BanPeriod.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: BanPeriod + + + + + + + + + + +
+ +

Class: BanPeriod

+ + + + + + +
+ +
+ +

BanPeriod() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new BanPeriod() → {React.Component}

+ + + + + + +
+

Ban period

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
duration + + +string + + + +

the period of banning the user its range is from 1 to 999 or parmenant

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Ban period component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/BanPopUp.html b/docs/BanPopUp.html new file mode 100644 index 00000000..2b4099ed --- /dev/null +++ b/docs/BanPopUp.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: BanPopUp + + + + + + + + + + +
+ +

Class: BanPopUp

+ + + + + + +
+ +
+ +

BanPopUp() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new BanPopUp() → {React.Component}

+ + + + + + +
+

Ban popup

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Ban popup component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/BanReason.html b/docs/BanReason.html new file mode 100644 index 00000000..3c090398 --- /dev/null +++ b/docs/BanReason.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: BanReason + + + + + + + + + + +
+ +

Class: BanReason

+ + + + + + +
+ +
+ +

BanReason() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new BanReason() → {React.Component}

+ + + + + + +
+

Ban reason

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
punishType + + +enum + + + +

it is the bunish type if the user is spam or Threatening, Harassing, Or Inciting Violence or Personal And Confidential Information or other reason

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • approved user instance
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/BannedUser.html b/docs/BannedUser.html new file mode 100644 index 00000000..88734d0c --- /dev/null +++ b/docs/BannedUser.html @@ -0,0 +1,384 @@ + + + + + JSDoc: Class: BannedUser + + + + + + + + + + +
+ +

Class: BannedUser

+ + + + + + +
+ +
+ +

BannedUser() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new BannedUser() → {React.Component}

+ + + + + + +
+

Banned user instace

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
username + + +string + + + +

username of banned user

profilePicture + + +string + + + +

link to banned user profile picture

banDate + + +string + + + +

the date that the user is banned at

punishType + + +enum + + + +

explain why this user is banned (spam or threatining etc...)

note + + +string + + + +

note from the moderator about the banned user

punishReason + + +string + + + +

extra details about the banned user

duration + + +string + + + +

the duration ban for the banned user it ranges from 0 to 999 and can be permenant

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Banned user instace component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/BannedUserList.html b/docs/BannedUserList.html new file mode 100644 index 00000000..79569805 --- /dev/null +++ b/docs/BannedUserList.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: BannedUserList + + + + + + + + + + +
+ +

Class: BannedUserList

+ + + + + + +
+ +
+ +

BannedUserList() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new BannedUserList() → {React.Component}

+ + + + + + +
+

banned user list

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • banned user list
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/BootstrapDialog.html b/docs/BootstrapDialog.html new file mode 100644 index 00000000..2505e08b --- /dev/null +++ b/docs/BootstrapDialog.html @@ -0,0 +1,349 @@ + + + + + JSDoc: Class: BootstrapDialog + + + + + + + + + + +
+ +

Class: BootstrapDialog

+ + + + + + +
+ +
+ +

BootstrapDialog() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new BootstrapDialog() → {React.Component}

+ + + + + + +
+

Alert when left description input and change it

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Alert when left description input and change it
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

BootstrapDialog() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new BootstrapDialog() → {React.Component}

+ + + + + + +
+

Alert when left list of topics input and change it

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Alert when left list of topics input and change it
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ChangeCountry.html b/docs/ChangeCountry.html new file mode 100644 index 00000000..6eb0b51f --- /dev/null +++ b/docs/ChangeCountry.html @@ -0,0 +1,294 @@ + + + + + JSDoc: Class: ChangeCountry + + + + + + + + + + +
+ +

Class: ChangeCountry

+ + + + + + +
+ +
+ +

ChangeCountry()

+ + +
+ +
+
+ + + + + + +

new ChangeCountry()

+ + + + + + +
+
    +
  • ChangeCountry
  • +
  • Change Country of user in settings page
  • +
+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
setValue + + +setPrefs + + + +

set perfs it will be Coutry of user

value + + +prefs + + + +

perfs of user

open + + +Boolean + + + +

bool to open list or close

handleChangeCoutry + + +function + + + +

handel when

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Comments.html b/docs/Comments.html new file mode 100644 index 00000000..b62b678c --- /dev/null +++ b/docs/Comments.html @@ -0,0 +1,399 @@ + + + + + JSDoc: Class: Comments + + + + + + + + + + +
+ +

Class: Comments

+ + + + + + +
+ +
+ +

Comments() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Comments() → {React.Component}

+ + + + + + +
+

Content component represents an entity of a comment

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
comment + + +object + + + +

conatin all info needed to be shown in the comment

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Comments

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

Comments() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Comments() → {React.Component}

+ + + + + + +
+

Search by Comments entity

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Search by community entity
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/CommentsContent.html b/docs/CommentsContent.html new file mode 100644 index 00000000..3a34a49c --- /dev/null +++ b/docs/CommentsContent.html @@ -0,0 +1,290 @@ + + + + + JSDoc: Class: CommentsContent + + + + + + + + + + +
+ +

Class: CommentsContent

+ + + + + + +
+ +
+ +

CommentsContent() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new CommentsContent() → {React.Component}

+ + + + + + +
+

the Body of an comment

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
points + + +string + + + +

number of points the comment did get

time + + +string + + + +

time of creating the comment

body + + +string + + + +

the body paragraph of the comment

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

CommentsContent

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/CommentsHeader.html b/docs/CommentsHeader.html new file mode 100644 index 00000000..d05473f3 --- /dev/null +++ b/docs/CommentsHeader.html @@ -0,0 +1,339 @@ + + + + + JSDoc: Class: CommentsHeader + + + + + + + + + + +
+ +

Class: CommentsHeader

+ + + + + + +
+ +
+ +

CommentsHeader(username) → {React.Component}

+ + +
+ +
+
+ + + + + + +

new CommentsHeader(username) → {React.Component}

+ + + + + + +
+

Header of the comment

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
username + + +string + + + +

name of the currently loggedin user.

+ + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subReddit + + +string + + + +

name of the subreddit in which is the comment.

publisher + + +string + + + +

author of the comment.

title + + +string + + + +

the title of a comment.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

CommentsHeader

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Communities.html b/docs/Communities.html new file mode 100644 index 00000000..0e430138 --- /dev/null +++ b/docs/Communities.html @@ -0,0 +1,397 @@ + + + + + JSDoc: Class: Communities + + + + + + + + + + +
+ +

Class: Communities

+ + + + + + +
+ +
+ +

Communities() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Communities() → {React.Component}

+ + + + + + +
+

This component is upper section of home page sidebar

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
communities + + +object + + + +

Object contains the title of the communities and list of them

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Communities

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

Communities() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Communities() → {React.Component}

+ + + + + + +
+

all comunities you afre a moderator of

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Communities

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/CommunitiesContainer.html b/docs/CommunitiesContainer.html new file mode 100644 index 00000000..628d83d9 --- /dev/null +++ b/docs/CommunitiesContainer.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: CommunitiesContainer + + + + + + + + + + +
+ +

Class: CommunitiesContainer

+ + + + + + +
+ +
+ +

CommunitiesContainer() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new CommunitiesContainer() → {React.Component}

+ + + + + + +
+

communities and their header

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
title + + +string + + + +

title of the communities

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • communities and their header
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/CommunitiesHeader.html b/docs/CommunitiesHeader.html new file mode 100644 index 00000000..0abf64a1 --- /dev/null +++ b/docs/CommunitiesHeader.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: CommunitiesHeader + + + + + + + + + + +
+ +

Class: CommunitiesHeader

+ + + + + + +
+ +
+ +

CommunitiesHeader() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new CommunitiesHeader() → {React.Component}

+ + + + + + +
+

header of the communities

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
explore + + +string + + + +

the explore page header

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • header of the communities
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/CommunitiesTab.html b/docs/CommunitiesTab.html new file mode 100644 index 00000000..0e4e3a73 --- /dev/null +++ b/docs/CommunitiesTab.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: CommunitiesTab + + + + + + + + + + +
+ +

Class: CommunitiesTab

+ + + + + + +
+ +
+ +

CommunitiesTab() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new CommunitiesTab() → {React.Component}

+ + + + + + +
+

the whole page of communities

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
title + + +string + + + +

the title of the communities section

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • communities page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Community.html b/docs/Community.html new file mode 100644 index 00000000..cf86932d --- /dev/null +++ b/docs/Community.html @@ -0,0 +1,470 @@ + + + + + JSDoc: Class: Community + + + + + + + + + + +
+ +

Class: Community

+ + + + + + +
+ +
+ +

Community() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Community() → {React.Component}

+ + + + + + +
+

community instance

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
communityName + + +string + + + +

the name of the community

communityPicture + + +string + + + +

the link of the community image

numOfMembers + + +string + + + +

number of members of the community

description + + +string + + + +

discription of the community

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • community component of explore page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

Community() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Community() → {React.Component}

+ + + + + + +
+

Search by posts sidebar community section

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Search by posts sidebar community section
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/CommunityItem.html b/docs/CommunityItem.html new file mode 100644 index 00000000..5c783a3b --- /dev/null +++ b/docs/CommunityItem.html @@ -0,0 +1,336 @@ + + + + + JSDoc: Class: CommunityItem + + + + + + + + + + +
+ +

Class: CommunityItem

+ + + + + + +
+ +
+ +

CommunityItem() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new CommunityItem() → {React.Component}

+ + + + + + +
+

This component represents the community in upper section of home page sidebar.

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
index + + +number + + + +

Community index.

icon + + +string + + + +

Community icon.

subredditName + + +string + + + +

Community name.

status + + +boolean + + + +

Community status.

isJoined + + +boolean + + + +

Check whether the logged in user is joined that community or not.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Communities

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/CommunityList.html b/docs/CommunityList.html new file mode 100644 index 00000000..5cd8decf --- /dev/null +++ b/docs/CommunityList.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Class: CommunityList + + + + + + + + + + +
+ +

Class: CommunityList

+ + + + + + +
+ +
+ +

CommunityList() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new CommunityList() → {React.Component}

+ + + + + + +
+

This component represents the list of communities on home page sidebar.

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
communities + + +Array.<community> + + + +

The list of communities.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Communities

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/CommunityMianTopic.html b/docs/CommunityMianTopic.html new file mode 100644 index 00000000..b195b9b6 --- /dev/null +++ b/docs/CommunityMianTopic.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Class: CommunityMianTopic + + + + + + + + + + +
+ +

Class: CommunityMianTopic

+ + + + + + +
+ +
+ +

CommunityMianTopic() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new CommunityMianTopic() → {React.Component}

+ + + + + + +
+

List of Primary topics in community

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
changeShow + + +function + + + +

show list of topics or not

ListSelected + + +function + + + +

to set the primary topic

handleClickAway + + +function + + + +

handel on select item

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Moderators section in sidebar
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Content.html b/docs/Content.html new file mode 100644 index 00000000..0b99eaf2 --- /dev/null +++ b/docs/Content.html @@ -0,0 +1,290 @@ + + + + + JSDoc: Class: Content + + + + + + + + + + +
+ +

Class: Content

+ + + + + + +
+ +
+ +

Content() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Content() → {React.Component}

+ + + + + + +
+

Content component display the comments and posts in the profile page

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
posts + + +array + + + +

array of posts objects

comments + + +array + + + +

array of comments objects

username + + +string + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Content

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/CreatePostContainer.html b/docs/CreatePostContainer.html new file mode 100644 index 00000000..0075eec3 --- /dev/null +++ b/docs/CreatePostContainer.html @@ -0,0 +1,193 @@ + + + + + JSDoc: Class: CreatePostContainer + + + + + + + + + + +
+ +

Class: CreatePostContainer

+ + + + + + +
+ +
+ +

CreatePostContainer() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new CreatePostContainer() → {React.Component}

+ + + + + + +
+

This component works as a container for all create post page components +and a repository the data fetched in

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Container represents the create post page

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/CreatePostForm.html b/docs/CreatePostForm.html new file mode 100644 index 00000000..b4b946dd --- /dev/null +++ b/docs/CreatePostForm.html @@ -0,0 +1,3169 @@ + + + + + JSDoc: Class: CreatePostForm + + + + + + + + + + +
+ +

Class: CreatePostForm

+ + + + + + +
+ +
+ +

CreatePostForm() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new CreatePostForm() → {React.Component}

+ + + + + + +
+

This component is the main section off create post page which holds the form to submit posts

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

CreatePostForm

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(inner) handleEnter()

+ + + + + + +
+

This function prevents user from type Enter in input fields

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleEnter()

+ + + + + + +
+

This function prevents user from type Enter in input fields

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handlePost()

+ + + + + + +
+

This function send post request to create post

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handlePost()

+ + + + + + +
+

This function send post request to create post

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handlePostTextChange()

+ + + + + + +
+

This function handles post text change

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handlePostType()

+ + + + + + +
+

This function handles post type change

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleSaveDraft()

+ + + + + + +
+

This function handles post text change

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleSendReplies()

+ + + + + + +
+

This function check if server should send email to user as a reply to the post

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleSendReplies()

+ + + + + + +
+

This function check if server should send email to user as a reply to the post

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleTitleChange()

+ + + + + + +
+

This function handles title change

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleTitleChange()

+ + + + + + +
+

This function handles title change

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleUrlChange()

+ + + + + + +
+

This function handles post url change

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) hanldeNsfw()

+ + + + + + +
+

This function handles if post is not safe for work or not

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) hanldeNsfw()

+ + + + + + +
+

This function handles if post is not safe for work or not

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) hanldeSpoiler()

+ + + + + + +
+

This function handles if post is spoiler or not

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) hanldeSpoiler()

+ + + + + + +
+

This function handles if post is spoiler or not

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

CreatePostForm() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new CreatePostForm() → {React.Component}

+ + + + + + +
+

This component is the main section off create post page which holds the form to submit posts

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

CreatePostForm

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(inner) handleEnter()

+ + + + + + +
+

This function prevents user from type Enter in input fields

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleEnter()

+ + + + + + +
+

This function prevents user from type Enter in input fields

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handlePost()

+ + + + + + +
+

This function send post request to create post

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handlePost()

+ + + + + + +
+

This function send post request to create post

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handlePostTextChange()

+ + + + + + +
+

This function handles post text change

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handlePostType()

+ + + + + + +
+

This function handles post type change

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleSaveDraft()

+ + + + + + +
+

This function handles post text change

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleSendReplies()

+ + + + + + +
+

This function check if server should send email to user as a reply to the post

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleSendReplies()

+ + + + + + +
+

This function check if server should send email to user as a reply to the post

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleTitleChange()

+ + + + + + +
+

This function handles title change

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleTitleChange()

+ + + + + + +
+

This function handles title change

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleUrlChange()

+ + + + + + +
+

This function handles post url change

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) hanldeNsfw()

+ + + + + + +
+

This function handles if post is not safe for work or not

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) hanldeNsfw()

+ + + + + + +
+

This function handles if post is not safe for work or not

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) hanldeSpoiler()

+ + + + + + +
+

This function handles if post is spoiler or not

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) hanldeSpoiler()

+ + + + + + +
+

This function handles if post is spoiler or not

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/CreatePostInHome.html b/docs/CreatePostInHome.html new file mode 100644 index 00000000..32f4f99e --- /dev/null +++ b/docs/CreatePostInHome.html @@ -0,0 +1,356 @@ + + + + + JSDoc: Class: CreatePostInHome + + + + + + + + + + +
+ +

Class: CreatePostInHome

+ + + + + + +
+ +
+ +

CreatePostInHome() → {React.Component|React.Component}

+ + +
+ +
+
+ + + + + + +

new CreatePostInHome() → {React.Component|React.Component}

+ + + + + + +
+

This component is the link between home page and create post page

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subredditName + + +number + + + +

creat post from a spacific subreddit or not

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+
    +
  • +
    +

    User avatar

    +
    + + + +
    +
    + Type +
    +
    + +React.Component + + +
    +
    +
  • + +
  • +
    +

    Inputs redirect user to create post page

    +
    + + + +
    +
    + Type +
    +
    + +React.Component + + +
    +
    +
  • +
+ + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(inner) handleClick()

+ + + + + + +
+

this function to redirect user to create post page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/DrawerBottom.html b/docs/DrawerBottom.html new file mode 100644 index 00000000..e5569bea --- /dev/null +++ b/docs/DrawerBottom.html @@ -0,0 +1,241 @@ + + + + + JSDoc: Class: DrawerBottom + + + + + + + + + + +
+ +

Class: DrawerBottom

+ + + + + + +
+ +
+ +

DrawerBottom(param0) → {React.Component}

+ + +
+ +
+
+ + + + + + +

new DrawerBottom(param0) → {React.Component}

+ + + + + + +
+

DrawerBottom

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
param0 + + +logInPopup + + + +

opening the register popup window

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

the bottom of the left permanent sidebar

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/EditBanFooter.html b/docs/EditBanFooter.html new file mode 100644 index 00000000..678e305a --- /dev/null +++ b/docs/EditBanFooter.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Class: EditBanFooter + + + + + + + + + + +
+ +

Class: EditBanFooter

+ + + + + + +
+ +
+ +

EditBanFooter() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new EditBanFooter() → {React.Component}

+ + + + + + +
+

EditBan popup footer

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClickCloseBan + + +function + + + +

close the popup

handleUnban + + +function + + + +

unban user and send data to the backend

handleEditBan + + +function + + + +

edit banned user data from the duration of be panned to the reason and the ban message etc

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • EditBan popup foooter
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/EditBanHaeder.html b/docs/EditBanHaeder.html new file mode 100644 index 00000000..203b81cb --- /dev/null +++ b/docs/EditBanHaeder.html @@ -0,0 +1,269 @@ + + + + + JSDoc: Class: EditBanHaeder + + + + + + + + + + +
+ +

Class: EditBanHaeder

+ + + + + + +
+ +
+ +

EditBanHaeder() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new EditBanHaeder() → {React.Component}

+ + + + + + +
+

EditBan popup header

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClickCloseBan + + +function + + + +

close the popup

userName + + +string + + + +

the username of banned user

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • EditBan popup header
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/EditBanPopUp.html b/docs/EditBanPopUp.html new file mode 100644 index 00000000..1c606034 --- /dev/null +++ b/docs/EditBanPopUp.html @@ -0,0 +1,338 @@ + + + + + JSDoc: Class: EditBanPopUp + + + + + + + + + + +
+ +

Class: EditBanPopUp

+ + + + + + +
+ +
+ +

EditBanPopUp() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new EditBanPopUp() → {React.Component}

+ + + + + + +
+

EditBan popup

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
userName + + +string + + + +

username of banned user

note + + +string + + + +

the moderator note about the banned user

punishReason + + +string + + + +

more details from the moderator about the banned user

punishType + + +enum + + + +

enum explain why this user is banned ( spam of threatining ... etc)

duration + + +string + + + +

the period that the user is banned it ranges from 0 to 999 or may be permenant

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • EditBan popup
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/EditPopUp.html b/docs/EditPopUp.html new file mode 100644 index 00000000..4f4cf208 --- /dev/null +++ b/docs/EditPopUp.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: EditPopUp + + + + + + + + + + +
+ +

Class: EditPopUp

+ + + + + + +
+ +
+ +

EditPopUp() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new EditPopUp() → {React.Component}

+ + + + + + +
+

Edit popup for moderator page

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
username + + +string + + + +

username of the moderator

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • edit moderator popup component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Email.html b/docs/Email.html new file mode 100644 index 00000000..e472a9c3 --- /dev/null +++ b/docs/Email.html @@ -0,0 +1,474 @@ + + + + + JSDoc: Class: Email + + + + + + + + + + +
+ +

Class: Email

+ + + + + + +
+ +
+ +

Email() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Email() → {React.Component}

+ + + + + + +
+

Email Compoenet with ReCAPTCHA if required

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
--email + + +object + + + +

email Taken from input field

--setEmail + + +function + + + +

set email object

--onSubmitFn + + +function + + + +

On Submit form

--loading + + +boolean + + + +

loading prop ofr RedditLoadingButton

--width + + +string + + + +

width of the form

--buttonText + + +string + + + +

text on the Submit button

--fieldText + + +string + + + +

text on the input field

--btnWidth + + +string + + + +

submit button width

--recaptcha + + +bool + + + +

if we ReCAPTCHA is required on not

--setVerified + + +function + + + +

to set that recaptcha is verified

--disabled + + +boolean + + + +

to disabled prop ofr RedditLoadingButton

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Email Form

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/EmptyApproved.html b/docs/EmptyApproved.html new file mode 100644 index 00000000..2ef84bf7 --- /dev/null +++ b/docs/EmptyApproved.html @@ -0,0 +1,190 @@ + + + + + JSDoc: Class: EmptyApproved + + + + + + + + + + +
+ +

Class: EmptyApproved

+ + + + + + +
+ +
+ +

EmptyApproved() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new EmptyApproved() → {React.Component}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • empty approved page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/EmptyBanned.html b/docs/EmptyBanned.html new file mode 100644 index 00000000..a2344a03 --- /dev/null +++ b/docs/EmptyBanned.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: EmptyBanned + + + + + + + + + + +
+ +

Class: EmptyBanned

+ + + + + + +
+ +
+ +

EmptyBanned() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new EmptyBanned() → {React.Component}

+ + + + + + +
+

empty ban page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • empty ban page component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/EmptyContent.html b/docs/EmptyContent.html new file mode 100644 index 00000000..4595ef9b --- /dev/null +++ b/docs/EmptyContent.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Class: EmptyContent + + + + + + + + + + +
+ +

Class: EmptyContent

+ + + + + + +
+ +
+ +

EmptyContent() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new EmptyContent() → {React.Component}

+ + + + + + +
+

the empty content when your having no posts nor comments

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
emptyContent + + +string + + + +

the string that should appear in the empty page

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

EmptyContent

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/EmptyMuted.html b/docs/EmptyMuted.html new file mode 100644 index 00000000..7586663c --- /dev/null +++ b/docs/EmptyMuted.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: EmptyMuted + + + + + + + + + + +
+ +

Class: EmptyMuted

+ + + + + + +
+ +
+ +

EmptyMuted() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new EmptyMuted() → {React.Component}

+ + + + + + +
+

empty muted page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • empty muted page component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Entity.html b/docs/Entity.html new file mode 100644 index 00000000..3553e105 --- /dev/null +++ b/docs/Entity.html @@ -0,0 +1,729 @@ + + + + + JSDoc: Class: Entity + + + + + + + + + + +
+ +

Class: Entity

+ + + + + + +
+ +
+ +

Entity() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Entity() → {React.Component}

+ + + + + + +
+

Entity of Flair

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
copied + + +function + + + +

copy id

Edited + + +function + + + +

show enable form

save + + +function + + + +

clase form and enable add

cancel + + +function + + + +

clase form and enable add

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Entity of Flair
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

Entity() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Entity() → {React.Component}

+ + + + + + +
+

Entity of Rule

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleExpand + + +function + + + +

show more details

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Entity of Rule
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

Entity() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Entity() → {React.Component}

+ + + + + + +
+

Rule Entity

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClick + + +function + + + +

toggle show rule or not

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Rule Entity
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ExploreHeader.html b/docs/ExploreHeader.html new file mode 100644 index 00000000..8be4d2db --- /dev/null +++ b/docs/ExploreHeader.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: ExploreHeader + + + + + + + + + + +
+ +

Class: ExploreHeader

+ + + + + + +
+ +
+ +

ExploreHeader() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ExploreHeader() → {React.Component}

+ + + + + + +
+

explore page header

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
headerSubtitle + + +string + + + +

the header title of the explore page

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • explore page header component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ExploreMainPage.html b/docs/ExploreMainPage.html new file mode 100644 index 00000000..816d73c7 --- /dev/null +++ b/docs/ExploreMainPage.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: ExploreMainPage + + + + + + + + + + +
+ +

Class: ExploreMainPage

+ + + + + + +
+ +
+ +

ExploreMainPage() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ExploreMainPage() → {React.Component}

+ + + + + + +
+

the explore main page

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
title + + +string + + + +

the title of the explore main page

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • the explore main page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Filter.html b/docs/Filter.html new file mode 100644 index 00000000..0a10a84d --- /dev/null +++ b/docs/Filter.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Class: Filter + + + + + + + + + + +
+ +

Class: Filter

+ + + + + + +
+ +
+ +

Filter() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Filter() → {React.Component}

+ + + + + + +
+

Navbar to filter posts by their category

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subTitle + + +string + + + +

title of page should navigate to

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Filter

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/FilterFull.html b/docs/FilterFull.html new file mode 100644 index 00000000..4a633034 --- /dev/null +++ b/docs/FilterFull.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Class: FilterFull + + + + + + + + + + +
+ +

Class: FilterFull

+ + + + + + +
+ +
+ +

FilterFull() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new FilterFull() → {React.Component}

+ + + + + + +
+

filter posts by their type for large screens

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subTitle + + +string + + + +

subTitle of page the user is currently in

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

FilterFull

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/FilterSearch.html b/docs/FilterSearch.html new file mode 100644 index 00000000..cefd6d1e --- /dev/null +++ b/docs/FilterSearch.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Class: FilterSearch + + + + + + + + + + +
+ +

Class: FilterSearch

+ + + + + + +
+ +
+ +

FilterSearch() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new FilterSearch() → {React.Component}

+ + + + + + +
+

filter Search by its type

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClick + + +function + + + +

navigate

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

filter Search by its type

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/FilterSmall.html b/docs/FilterSmall.html new file mode 100644 index 00000000..af1312ca --- /dev/null +++ b/docs/FilterSmall.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Class: FilterSmall + + + + + + + + + + +
+ +

Class: FilterSmall

+ + + + + + +
+ +
+ +

FilterSmall() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new FilterSmall() → {React.Component}

+ + + + + + +
+

Filter the posts by type for small screens

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subTitle + + +string + + + +

subTitle of page the user is currently in

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

FilterSmall

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/FirstParty.html b/docs/FirstParty.html new file mode 100644 index 00000000..c2562fa0 --- /dev/null +++ b/docs/FirstParty.html @@ -0,0 +1,345 @@ + + + + + JSDoc: Class: FirstParty + + + + + + + + + + +
+ +

Class: FirstParty

+ + + + + + +
+ +
+ +

FirstParty() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new FirstParty() → {React.Component}

+ + + + + + +
+

Form for Logging in by username and passsword

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

First Party Form

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

FirstParty() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new FirstParty() → {React.Component}

+ + + + + + +
+

Form for Logging in by username and passsword

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

First Party Form

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Flirt.html b/docs/Flirt.html new file mode 100644 index 00000000..53d1420a --- /dev/null +++ b/docs/Flirt.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: Flirt + + + + + + + + + + +
+ +

Class: Flirt

+ + + + + + +
+ +
+ +

Flirt() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Flirt() → {React.Component}

+ + + + + + +
+

Filter section

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Filter section
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Footer.html b/docs/Footer.html new file mode 100644 index 00000000..fd8a4706 --- /dev/null +++ b/docs/Footer.html @@ -0,0 +1,315 @@ + + + + + JSDoc: Class: Footer + + + + + + + + + + +
+ +

Class: Footer

+ + + + + + +
+ +
+ +

Footer() → {React.Component}

+ + +
+ +
+
+ + + + + + + + + + + + + +
+

Footer of popups for user management section

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
firstButtonFunction + + +function + + + +

the first button functionality

firstButtonText + + +string + + + +

the first button label

secondButtonFuncion + + +function + + + +

the second button functionality

secondButtonText + + +string + + + +

the second button label

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Footer component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ForgetPassword.html b/docs/ForgetPassword.html new file mode 100644 index 00000000..1a0d5c14 --- /dev/null +++ b/docs/ForgetPassword.html @@ -0,0 +1,345 @@ + + + + + JSDoc: Class: ForgetPassword + + + + + + + + + + +
+ +

Class: ForgetPassword

+ + + + + + +
+ +
+ +

ForgetPassword() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ForgetPassword() → {React.Component}

+ + + + + + +
+

Component for Forget Password Page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

--ForgetPassword Page Component

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

ForgetPassword() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ForgetPassword() → {React.Component}

+ + + + + + +
+

ForgetPassword popUp

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

main body of forget password popup

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ForgetUsername.html b/docs/ForgetUsername.html new file mode 100644 index 00000000..5a0bb745 --- /dev/null +++ b/docs/ForgetUsername.html @@ -0,0 +1,345 @@ + + + + + JSDoc: Class: ForgetUsername + + + + + + + + + + +
+ +

Class: ForgetUsername

+ + + + + + +
+ +
+ +

ForgetUsername() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ForgetUsername() → {React.Component}

+ + + + + + +
+

Component for Forget Username Page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

--Forget Username page

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

ForgetUsername() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ForgetUsername() → {React.Component}

+ + + + + + +
+

ForgetUsername popUp

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

main body of forget username popup

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/FormDialog.html b/docs/FormDialog.html new file mode 100644 index 00000000..813553b2 --- /dev/null +++ b/docs/FormDialog.html @@ -0,0 +1,825 @@ + + + + + JSDoc: Class: FormDialog + + + + + + + + + + +
+ +

Class: FormDialog

+ + + + + + +
+ +
+ +

FormDialog() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new FormDialog() → {React.Component}

+ + + + + + +
+

Pop up Creat Cummunity Form

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Popup Form
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(async, inner) Submit(e)

+ + + + + + +
+

make post action

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
e + + +object + + + +

sbmit button

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(async, inner) check()

+ + + + + + +
+

this function to show message when bluring of the input feild if it is empty

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) check18()

+ + + + + + +
+

this function to click checkbox on click the text next to it

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleChange(event)

+ + + + + + +
+

this function to know if Subreddit Name reach max(21) or not +to prevent type more than 21 char in the input field and calculate number of char in input feild

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
event + + +object + + + +

the input field

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleClickOpen()

+ + + + + + +
+

this function to open the popup form on click the button

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleClose()

+ + + + + + +
+

this function to close the popup form on click cancel , x , outside the form

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Header.html b/docs/Header.html new file mode 100644 index 00000000..66cbb26e --- /dev/null +++ b/docs/Header.html @@ -0,0 +1,720 @@ + + + + + JSDoc: Class: Header + + + + + + + + + + +
+ +

Class: Header

+ + + + + + +
+ +
+ +

Header(props) → {React.Component}

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
props + + +object + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

-Header for pop up form

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

Header() → {React.Component}

+ + +
+ +
+
+ + + + + + + + + + + + + +
+

Header of popups for user management section

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
buttonFunction + + +function + + + +

the button functionality

headerText + + +string + + + +

the label of the header

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Header component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

Header() → {React.Component}

+ + +
+ +
+
+ + + + + + + + + + + + + +
+

Subreddit page

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
redirect + + +function + + + +

redirect to homepage

createCommunity + + +function + + + +

open create community form

sendData + + +function + + + +

send data to backend

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Subreddit page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/HomeList.html b/docs/HomeList.html new file mode 100644 index 00000000..982bd274 --- /dev/null +++ b/docs/HomeList.html @@ -0,0 +1,345 @@ + + + + + JSDoc: Class: HomeList + + + + + + + + + + +
+ +

Class: HomeList

+ + + + + + +
+ +
+ +

HomeList() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new HomeList() → {React.Component}

+ + + + + + +
+

HomeList

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

left list in navbar in logged in mode

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

HomeList() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new HomeList() → {React.Component}

+ + + + + + +
+

Home List

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

the left list in the navbar in signed out mode.

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/HomePageContainer.html b/docs/HomePageContainer.html new file mode 100644 index 00000000..ee1782b3 --- /dev/null +++ b/docs/HomePageContainer.html @@ -0,0 +1,193 @@ + + + + + JSDoc: Class: HomePageContainer + + + + + + + + + + +
+ +

Class: HomePageContainer

+ + + + + + +
+ +
+ +

HomePageContainer() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new HomePageContainer() → {React.Component}

+ + + + + + +
+

This component works as a container for all home page components +and a repository the data fetched in

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Container represents the home page

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/HomePageFooter.html b/docs/HomePageFooter.html new file mode 100644 index 00000000..4fb00142 --- /dev/null +++ b/docs/HomePageFooter.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: HomePageFooter + + + + + + + + + + +
+ +

Class: HomePageFooter

+ + + + + + +
+ +
+ +

HomePageFooter() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new HomePageFooter() → {React.Component}

+ + + + + + +
+

This component is the footer of the page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Footer

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Input.html b/docs/Input.html new file mode 100644 index 00000000..dd487221 --- /dev/null +++ b/docs/Input.html @@ -0,0 +1,237 @@ + + + + + JSDoc: Class: Input + + + + + + + + + + +
+ +

Class: Input

+ + + + + + +
+ +
+ +

Input(props) → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Input(props) → {React.Component}

+ + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
props + + +object + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

-input for pop up form

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/InvitationPopUp.html b/docs/InvitationPopUp.html new file mode 100644 index 00000000..a139108b --- /dev/null +++ b/docs/InvitationPopUp.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: InvitationPopUp + + + + + + + + + + +
+ +

Class: InvitationPopUp

+ + + + + + +
+ +
+ +

InvitationPopUp() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new InvitationPopUp() → {React.Component}

+ + + + + + +
+

invitation popup for moderator page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • invite moderator popup component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/JoinButton.html b/docs/JoinButton.html new file mode 100644 index 00000000..7d530ceb --- /dev/null +++ b/docs/JoinButton.html @@ -0,0 +1,512 @@ + + + + + JSDoc: Class: JoinButton + + + + + + + + + + +
+ +

Class: JoinButton

+ + + + + + +
+ +
+ +

JoinButton() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new JoinButton() → {React.Component}

+ + + + + + +
+

This component is join button

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
isJoined + + +boolean + + + +

Check whether the user joined the subreddit or not.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Join button

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(inner) handleClick()

+ + + + + + +
+

this function toggles the join state of the user

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleMouseIn()

+ + + + + + +
+

this function display leave to user if he have already joined the community while hovering

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleMouseOut()

+ + + + + + +
+

this function display joined to user if he have already joined the community while not hovering

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/LeavePopUp.html b/docs/LeavePopUp.html new file mode 100644 index 00000000..ac2d335b --- /dev/null +++ b/docs/LeavePopUp.html @@ -0,0 +1,269 @@ + + + + + JSDoc: Class: LeavePopUp + + + + + + + + + + +
+ +

Class: LeavePopUp

+ + + + + + +
+ +
+ +

LeavePopUp() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new LeavePopUp() → {React.Component}

+ + + + + + +
+

Leave moderator popup for moderator page

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
openLeave + + +boolean + + + +

determine the state of the popup (opened or closed)

handleClickCloseLeave + + +function + + + +

close the popup

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • invite moderator popup component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/LogInPage.html b/docs/LogInPage.html new file mode 100644 index 00000000..71ba316a --- /dev/null +++ b/docs/LogInPage.html @@ -0,0 +1,175 @@ + + + + + JSDoc: Class: LogInPage + + + + + + + + + + +
+ +

Class: LogInPage

+ + + + + + +
+ +
+ +

LogInPage()

+ + +
+ +
+
+ + + + + + +

new LogInPage()

+ + + + + + +
+

Component For Login Page Route='/login'

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
Example
+ +
return (
  <LogInPage/>
)
+ + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/LogoIcon.html b/docs/LogoIcon.html new file mode 100644 index 00000000..eacc82d5 --- /dev/null +++ b/docs/LogoIcon.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: LogoIcon + + + + + + + + + + +
+ +

Class: LogoIcon

+ + + + + + +
+ +
+ +

LogoIcon() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new LogoIcon() → {React.Component}

+ + + + + + +
+

LogoIcon

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

logo and nonlegit word beside it.

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/MainContent.html b/docs/MainContent.html new file mode 100644 index 00000000..c8d1b43b --- /dev/null +++ b/docs/MainContent.html @@ -0,0 +1,268 @@ + + + + + JSDoc: Class: MainContent + + + + + + + + + + +
+ +

Class: MainContent

+ + + + + + +
+ +
+ +

MainContent() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new MainContent() → {React.Component}

+ + + + + + +
+

This component works as a container for the left half components +like timeline

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
children + + +React.Component + + + +

Components which will be wrapped in main container

width + + +number + + + +

The maximum width of the main content

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Container represents its children

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Moderation.html b/docs/Moderation.html new file mode 100644 index 00000000..4dd84e08 --- /dev/null +++ b/docs/Moderation.html @@ -0,0 +1,315 @@ + + + + + JSDoc: Class: Moderation + + + + + + + + + + +
+ +

Class: Moderation

+ + + + + + +
+ +
+ +

Moderation() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Moderation() → {React.Component}

+ + + + + + +
+

About section in sidebar for moderators only instead of about section for normal users

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
changeShow + + +function + + + +

show select list or not

sendData + + +function + + + +

send data to backend

ListSelected + + +function + + + +

handel on select item

handleClickAway + + +function + + + +

close the list in click away

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • About section in sidebar for moderators only instead of about section for normal users
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Moderator.html b/docs/Moderator.html new file mode 100644 index 00000000..3d698894 --- /dev/null +++ b/docs/Moderator.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: Moderator + + + + + + + + + + +
+ +

Class: Moderator

+ + + + + + +
+ +
+ +

Moderator() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Moderator() → {React.Component}

+ + + + + + +
+

moderators whole page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • mdoerators page component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ModeratorList.html b/docs/ModeratorList.html new file mode 100644 index 00000000..455c4e3f --- /dev/null +++ b/docs/ModeratorList.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: ModeratorList + + + + + + + + + + +
+ +

Class: ModeratorList

+ + + + + + +
+ +
+ +

ModeratorList() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ModeratorList() → {React.Component}

+ + + + + + +
+

list of the functionality of the moderator for smaller screens

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

ModeratorList

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Moderators.html b/docs/Moderators.html new file mode 100644 index 00000000..4e696b34 --- /dev/null +++ b/docs/Moderators.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: Moderators + + + + + + + + + + +
+ +

Class: Moderators

+ + + + + + +
+ +
+ +

Moderators() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Moderators() → {React.Component}

+ + + + + + +
+

Moderators section in sidebar

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Moderators section in sidebar
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ModeratorsList.html b/docs/ModeratorsList.html new file mode 100644 index 00000000..feee45af --- /dev/null +++ b/docs/ModeratorsList.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: ModeratorsList + + + + + + + + + + +
+ +

Class: ModeratorsList

+ + + + + + +
+ +
+ +

ModeratorsList() → {React.Component}

+ + +
+ + + +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/MoreDetails.html b/docs/MoreDetails.html new file mode 100644 index 00000000..fd0de7c6 --- /dev/null +++ b/docs/MoreDetails.html @@ -0,0 +1,522 @@ + + + + + JSDoc: Class: MoreDetails + + + + + + + + + + +
+ +

Class: MoreDetails

+ + + + + + +
+ +
+ +

MoreDetails() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new MoreDetails() → {React.Component}

+ + + + + + +
+

more datails tab

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
isOpened + + +boolean + + + +

determine the state of more details tab to be showed or hidden

bannedFor + + +enum + + + +

explain why this user is banned (spam or threatining etc...)

modNote + + +string + + + +

note from the moderator about the banned user

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • more details tab
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

MoreDetails() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new MoreDetails() → {React.Component}

+ + + + + + +
+

more datails tab

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
isOpened + + +boolean + + + +

determine the state of more details tab to be showed or hidden

modNote + + +string + + + +

note from the moderator about the muted user

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • more details tab
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Mute.html b/docs/Mute.html new file mode 100644 index 00000000..0c76bf5d --- /dev/null +++ b/docs/Mute.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: Mute + + + + + + + + + + +
+ +

Class: Mute

+ + + + + + +
+ +
+ +

Mute() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Mute() → {React.Component}

+ + + + + + +
+

the whole page of muted

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • muted user page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/MuteMessage.html b/docs/MuteMessage.html new file mode 100644 index 00000000..248e99e0 --- /dev/null +++ b/docs/MuteMessage.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: MuteMessage + + + + + + + + + + +
+ +

Class: MuteMessage

+ + + + + + +
+ +
+ +

MuteMessage() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new MuteMessage() → {React.Component}

+ + + + + + +
+

mute message

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • mute message component (text area)
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/MutePopUp.html b/docs/MutePopUp.html new file mode 100644 index 00000000..5c3448d0 --- /dev/null +++ b/docs/MutePopUp.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: MutePopUp + + + + + + + + + + +
+ +

Class: MutePopUp

+ + + + + + +
+ +
+ +

MutePopUp() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new MutePopUp() → {React.Component}

+ + + + + + +
+

mute popup

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • mute popup component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/MutedUser.html b/docs/MutedUser.html new file mode 100644 index 00000000..b32af2dd --- /dev/null +++ b/docs/MutedUser.html @@ -0,0 +1,269 @@ + + + + + JSDoc: Class: MutedUser + + + + + + + + + + +
+ +

Class: MutedUser

+ + + + + + +
+ +
+ +

MutedUser() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new MutedUser() → {React.Component}

+ + + + + + +
+

Banned user instace

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
user + + +object + + + +

an object containing all information about the user from its username until the link to the its profile picture and the date that user is muted

muteInfo + + +object + + + +

contain the comment of the moderator on the muted user

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Banned user instace component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/MutedUserList.html b/docs/MutedUserList.html new file mode 100644 index 00000000..f0b68fe8 --- /dev/null +++ b/docs/MutedUserList.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: MutedUserList + + + + + + + + + + +
+ +

Class: MutedUserList

+ + + + + + +
+ +
+ +

MutedUserList() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new MutedUserList() → {React.Component}

+ + + + + + +
+

muted user list

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • muted user list
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/NavIcons.html b/docs/NavIcons.html new file mode 100644 index 00000000..6657cadf --- /dev/null +++ b/docs/NavIcons.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: NavIcons + + + + + + + + + + +
+ +

Class: NavIcons

+ + + + + + +
+ +
+ +

NavIcons() → {React.Component}

+ + +
+ +
+
+ + + + + + + + + + + + + +
+

NavIcons

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

the three icons in the navbar (Popular - notifications - create post)

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Navbar.html b/docs/Navbar.html new file mode 100644 index 00000000..7879a598 --- /dev/null +++ b/docs/Navbar.html @@ -0,0 +1,193 @@ + + + + + JSDoc: Class: Navbar + + + + + + + + + + +
+ +

Class: Navbar

+ + + + + + +
+ +
+ +

Navbar() → {React.Component}

+ + +
+ +
+
+ + + + + + + + + + + + + +
+

Navbar

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

the whole logged in navbar with the two lists, +Search bar and icon buttons

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/NoResult.html b/docs/NoResult.html new file mode 100644 index 00000000..3ff8166b --- /dev/null +++ b/docs/NoResult.html @@ -0,0 +1,269 @@ + + + + + JSDoc: Class: NoResult + + + + + + + + + + +
+ +

Class: NoResult

+ + + + + + +
+ +
+ +

NoResult() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new NoResult() → {React.Component}

+ + + + + + +
+

the whole page of no result that appears when try to seach on a user in user managment section in moderatio page

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
query + + +string + + + +

it is the query in the search input field

childToParent + + +function + + + +

it is a function state to pass the query from the child (search bar) to its parent (user management list)

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • no result page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/NonEmptyModerator.html b/docs/NonEmptyModerator.html new file mode 100644 index 00000000..1fa26bce --- /dev/null +++ b/docs/NonEmptyModerator.html @@ -0,0 +1,430 @@ + + + + + JSDoc: Class: NonEmptyModerator + + + + + + + + + + +
+ +

Class: NonEmptyModerator

+ + + + + + +
+ +
+ +

NonEmptyModerator() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new NonEmptyModerator() → {React.Component}

+ + + + + + +
+

non empty moderator page

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
username + + +string + + + +

the username of the moderator

profilePicture + + +string + + + +

it is the link to the profile picture of the moderator

modDate + + +string + + + +

it is the date to be a moderator

all + + +boolean + + + +

indicates that the moderator has all privileges

access + + +boolean + + + +

indicates that tha moderator has the control on user

confing + + +boolean + + + +

indicates that the moderator has the control on settings

flair + + +boolean + + + +

indicates that the moderator has the control on post flairs

posts + + +boolean + + + +

indicates that the moderator has the control on posts

type + + +integer + + + +

determine the type of moderators if invited or arleady a moderator

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • non empty moderator page component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/NotificationCategories.html b/docs/NotificationCategories.html new file mode 100644 index 00000000..2aa5c976 --- /dev/null +++ b/docs/NotificationCategories.html @@ -0,0 +1,358 @@ + + + + + JSDoc: Class: NotificationCategories + + + + + + + + + + +
+ +

Class: NotificationCategories

+ + + + + + +
+ +
+ +

NotificationCategories(earlier, today, handleClose, handleClick, open, anchorEl) → {React.Component}

+ + +
+ +
+
+ + + + + + +

new NotificationCategories(earlier, today, handleClose, handleClick, open, anchorEl) → {React.Component}

+ + + + + + +
+

Notification Categories

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
earlier + + +Array + + + +

Array of earlier notifications

today + + +Array + + + +

type of today notifiactions

handleClose + + +function + + + +

function to set what notifiacation we select and it's type

handleClick + + +function + + + +

function to handel deleteing when click hide

open + + +Boolean + + + +

bool to set open or close

anchorEl + + +object + + + +

anchor element

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Retrun all notificaions dependent on type today or earlier
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/NotificationImages.html b/docs/NotificationImages.html new file mode 100644 index 00000000..8eae31b3 --- /dev/null +++ b/docs/NotificationImages.html @@ -0,0 +1,243 @@ + + + + + JSDoc: Class: NotificationImages + + + + + + + + + + +
+ +

Class: NotificationImages

+ + + + + + +
+ +
+ +

NotificationImages(value) → {React.Component}

+ + +
+ +
+
+ + + + + + +

new NotificationImages(value) → {React.Component}

+ + + + + + +
+

NotificationImages

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +string + + + +

type of notifiaction

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Retrun all image beside notification body
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Notifications.html b/docs/Notifications.html new file mode 100644 index 00000000..0675f2b1 --- /dev/null +++ b/docs/Notifications.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: Notifications + + + + + + + + + + +
+ +

Class: Notifications

+ + + + + + +
+ +
+ +

Notifications() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Notifications() → {React.Component}

+ + + + + + +
+

Notifications page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • All Notifications page sections
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/NotificationsBody.html b/docs/NotificationsBody.html new file mode 100644 index 00000000..a174ef6f --- /dev/null +++ b/docs/NotificationsBody.html @@ -0,0 +1,272 @@ + + + + + JSDoc: Class: NotificationsBody + + + + + + + + + + +
+ +

Class: NotificationsBody

+ + + + + + +
+ +
+ +

NotificationsBody() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new NotificationsBody() → {React.Component}

+ + + + + + +
+
    +
  • Notifications Body
  • +
  • fech notifications data from api
  • +
+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClick + + +function + + + +

to set what notifiacation we select and it's type

handel + + +function + + + +

deleteing when click hide

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Body of each Notification depandent it's type
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfileArrowList.html b/docs/OtherProfileArrowList.html new file mode 100644 index 00000000..2f080dc5 --- /dev/null +++ b/docs/OtherProfileArrowList.html @@ -0,0 +1,267 @@ + + + + + JSDoc: Class: OtherProfileArrowList + + + + + + + + + + +
+ +

Class: OtherProfileArrowList

+ + + + + + +
+ +
+ +

OtherProfileArrowList() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfileArrowList() → {React.Component}

+ + + + + + +
+

the upvoted and downvoted arrows in responsive postfooter

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
points + + +number + + + +

get number of upvotes or downvotes on a post

postVoteStatus + + +number + + + +

get if the post is upvoted or downvoted or none

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

ArrowList

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfileCommunities.html b/docs/OtherProfileCommunities.html new file mode 100644 index 00000000..fe2fc972 --- /dev/null +++ b/docs/OtherProfileCommunities.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: OtherProfileCommunities + + + + + + + + + + +
+ +

Class: OtherProfileCommunities

+ + + + + + +
+ +
+ +

OtherProfileCommunities() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfileCommunities() → {React.Component}

+ + + + + + +
+

all comunities you afre a moderator of

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfileCommunities

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfileContent.html b/docs/OtherProfileContent.html new file mode 100644 index 00000000..feac0bee --- /dev/null +++ b/docs/OtherProfileContent.html @@ -0,0 +1,290 @@ + + + + + JSDoc: Class: OtherProfileContent + + + + + + + + + + +
+ +

Class: OtherProfileContent

+ + + + + + +
+ +
+ +

OtherProfileContent() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfileContent() → {React.Component}

+ + + + + + +
+

Content component display the comments and posts in the profile page

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
posts + + +array + + + +

array of posts objects

comments + + +array + + + +

array of comments objects

username + + +string + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfileContent

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfileEmptyContent.html b/docs/OtherProfileEmptyContent.html new file mode 100644 index 00000000..818a30a6 --- /dev/null +++ b/docs/OtherProfileEmptyContent.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Class: OtherProfileEmptyContent + + + + + + + + + + +
+ +

Class: OtherProfileEmptyContent

+ + + + + + +
+ +
+ +

OtherProfileEmptyContent() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfileEmptyContent() → {React.Component}

+ + + + + + +
+

the empty content when your having no posts nor comments

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
emptyContent + + +string + + + +

the string that should appear in the empty page

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfileEmptyContent

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfileFilter.html b/docs/OtherProfileFilter.html new file mode 100644 index 00000000..b425c993 --- /dev/null +++ b/docs/OtherProfileFilter.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Class: OtherProfileFilter + + + + + + + + + + +
+ +

Class: OtherProfileFilter

+ + + + + + +
+ +
+ +

OtherProfileFilter() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfileFilter() → {React.Component}

+ + + + + + +
+

Navbar to filter posts by their category

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subTitle + + +string + + + +

title of page should navigate to

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfileFilter

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfileFilterFull.html b/docs/OtherProfileFilterFull.html new file mode 100644 index 00000000..67b1e9d3 --- /dev/null +++ b/docs/OtherProfileFilterFull.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Class: OtherProfileFilterFull + + + + + + + + + + +
+ +

Class: OtherProfileFilterFull

+ + + + + + +
+ +
+ +

OtherProfileFilterFull() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfileFilterFull() → {React.Component}

+ + + + + + +
+

filter posts by their type for large screens

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subTitle + + +string + + + +

subTitle of page the user is currently in

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfileFilterFull

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfileFilterSmall.html b/docs/OtherProfileFilterSmall.html new file mode 100644 index 00000000..992b377f --- /dev/null +++ b/docs/OtherProfileFilterSmall.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Class: OtherProfileFilterSmall + + + + + + + + + + +
+ +

Class: OtherProfileFilterSmall

+ + + + + + +
+ +
+ +

OtherProfileFilterSmall() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfileFilterSmall() → {React.Component}

+ + + + + + +
+

Filter the posts by type for small screens

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subTitle + + +string + + + +

subTitle of page the user is currently in

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfileFilterSmall

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfileHeader.html b/docs/OtherProfileHeader.html new file mode 100644 index 00000000..45bef494 --- /dev/null +++ b/docs/OtherProfileHeader.html @@ -0,0 +1,387 @@ + + + + + JSDoc: Class: OtherProfileHeader + + + + + + + + + + +
+ +

Class: OtherProfileHeader

+ + + + + + +
+ +
+ +

OtherProfileHeader() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfileHeader() → {React.Component}

+ + + + + + +
+

OtherProfileHeader

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClick + + +function + + + +

to navigate to the subpage

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • OtherProfileHeader
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(inner) handleClick(subPage)

+ + + + + + +
+

this function to navigate between the taps

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subPage + + +string + + + +

the page to navigate to

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfileMainContent.html b/docs/OtherProfileMainContent.html new file mode 100644 index 00000000..aea79617 --- /dev/null +++ b/docs/OtherProfileMainContent.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: OtherProfileMainContent + + + + + + + + + + +
+ +

Class: OtherProfileMainContent

+ + + + + + +
+ +
+ +

OtherProfileMainContent() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfileMainContent() → {React.Component}

+ + + + + + +
+

OtherProfileMainContent if the profile page

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClick + + +function + + + +

to navigate to the subpage

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • OtherProfileMainContent
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfilePost.html b/docs/OtherProfilePost.html new file mode 100644 index 00000000..1707ba2e --- /dev/null +++ b/docs/OtherProfilePost.html @@ -0,0 +1,267 @@ + + + + + JSDoc: Class: OtherProfilePost + + + + + + + + + + +
+ +

Class: OtherProfilePost

+ + + + + + +
+ +
+ +

OtherProfilePost() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfilePost() → {React.Component}

+ + + + + + +
+

the post that appear in posts - saved - hidden - upvoted - downvotep taps

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
entity + + +object + + + +

an entity conatins all post informations

type + + +string + + + +

subTitle of the page

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfilePost

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfilePostFooter.html b/docs/OtherProfilePostFooter.html new file mode 100644 index 00000000..2d809796 --- /dev/null +++ b/docs/OtherProfilePostFooter.html @@ -0,0 +1,290 @@ + + + + + JSDoc: Class: OtherProfilePostFooter + + + + + + + + + + +
+ +

Class: OtherProfilePostFooter

+ + + + + + +
+ +
+ +

OtherProfilePostFooter() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfilePostFooter() → {React.Component}

+ + + + + + +
+

Footer of the post that contain all icons

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleExpand + + +function + + + +

pass the event to the parent to show the paragraph of the post

expand + + +state + + + +

pass a state to the parent to change the icon

entity + + +object + + + +

contains all info of the post

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfilePostFooter

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfilePostFooterListResponsive.html b/docs/OtherProfilePostFooterListResponsive.html new file mode 100644 index 00000000..3bdb54fe --- /dev/null +++ b/docs/OtherProfilePostFooterListResponsive.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: OtherProfilePostFooterListResponsive + + + + + + + + + + +
+ +

Class: OtherProfilePostFooterListResponsive

+ + + + + + +
+ +
+ +

OtherProfilePostFooterListResponsive() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfilePostFooterListResponsive() → {React.Component}

+ + + + + + +
+

resposive list of the post footer

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfilePostFooterListResponsive

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfilePostHeader.html b/docs/OtherProfilePostHeader.html new file mode 100644 index 00000000..92752948 --- /dev/null +++ b/docs/OtherProfilePostHeader.html @@ -0,0 +1,290 @@ + + + + + JSDoc: Class: OtherProfilePostHeader + + + + + + + + + + +
+ +

Class: OtherProfilePostHeader

+ + + + + + +
+ +
+ +

OtherProfilePostHeader() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfilePostHeader() → {React.Component}

+ + + + + + +
+

Header of the post

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
nameUser + + +string + + + +

name of the currently loggedin user

Time + + +string + + + +

contains the time of the post

nameUser + + +string + + + +

contains the name of subreddit the post piblished in

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfilePostHeader

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfilePostSide.html b/docs/OtherProfilePostSide.html new file mode 100644 index 00000000..96e0cdd2 --- /dev/null +++ b/docs/OtherProfilePostSide.html @@ -0,0 +1,267 @@ + + + + + JSDoc: Class: OtherProfilePostSide + + + + + + + + + + +
+ +

Class: OtherProfilePostSide

+ + + + + + +
+ +
+ +

OtherProfilePostSide() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfilePostSide() → {React.Component}

+ + + + + + +
+

Sidebar of the post conatining arrow up and down

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
points + + +number + + + +

number of votes on a post

postVoteStatus + + +number + + + +

is the post upvoted or down voted or none

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfilePostSide

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfilePostsTap.html b/docs/OtherProfilePostsTap.html new file mode 100644 index 00000000..9b478ffc --- /dev/null +++ b/docs/OtherProfilePostsTap.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: OtherProfilePostsTap + + + + + + + + + + +
+ +

Class: OtherProfilePostsTap

+ + + + + + +
+ +
+ +

OtherProfilePostsTap() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfilePostsTap() → {React.Component}

+ + + + + + +
+

posts tap in my profile

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfilePostsTap

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfileSidebar.html b/docs/OtherProfileSidebar.html new file mode 100644 index 00000000..708b74d9 --- /dev/null +++ b/docs/OtherProfileSidebar.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: OtherProfileSidebar + + + + + + + + + + +
+ +

Class: OtherProfileSidebar

+ + + + + + +
+ +
+ +

OtherProfileSidebar() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfileSidebar() → {React.Component}

+ + + + + + +
+

sidebar in profile containing the userinfo and communities you are a moderator of

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfileSidebar

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/OtherProfileUserInfo.html b/docs/OtherProfileUserInfo.html new file mode 100644 index 00000000..e702a793 --- /dev/null +++ b/docs/OtherProfileUserInfo.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: OtherProfileUserInfo + + + + + + + + + + +
+ +

Class: OtherProfileUserInfo

+ + + + + + +
+ +
+ +

OtherProfileUserInfo() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new OtherProfileUserInfo() → {React.Component}

+ + + + + + +
+

UserInfo Box in sidebar containing all info of a user

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

OtherProfileUserInfo

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/People.html b/docs/People.html new file mode 100644 index 00000000..da0fcfb6 --- /dev/null +++ b/docs/People.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: People + + + + + + + + + + +
+ +

Class: People

+ + + + + + +
+ +
+ +

People() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new People() → {React.Component}

+ + + + + + +
+

Search by posts sidebar people section

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Search by posts sidebar people section
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Peoples.html b/docs/Peoples.html new file mode 100644 index 00000000..c2233d95 --- /dev/null +++ b/docs/Peoples.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Class: Peoples + + + + + + + + + + +
+ +

Class: Peoples

+ + + + + + +
+ +
+ +

Peoples() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Peoples() → {React.Component}

+ + + + + + +
+

Search by people

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleJoin + + +function + + + +

send follow to backend

handleMouseIn + + +function + + + +

when hover set buttom value to unfollow

handleMouseOut + + +function + + + +

when out of hover set button value to follow

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Search by people
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PersonalReddit.html b/docs/PersonalReddit.html new file mode 100644 index 00000000..305f6e4d --- /dev/null +++ b/docs/PersonalReddit.html @@ -0,0 +1,446 @@ + + + + + JSDoc: Class: PersonalReddit + + + + + + + + + + +
+ +

Class: PersonalReddit

+ + + + + + +
+ +
+ +

PersonalReddit() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PersonalReddit() → {React.Component}

+ + + + + + +
+

This component contains info about personal +Reddit frontpage.

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
title + + +string + + + +

Title of personal reddit

paragraph + + +string + + + +

Paragraph of personal reddit

image + + +string + + + +

Image of personal reddit

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Buttons to show info about communities

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

PersonalReddit() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PersonalReddit() → {React.Component}

+ + + + + + +
+

pesronal reddit in search by posts sidebar

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • pesronal reddit in search by posts sidebar
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PopularContainer.html b/docs/PopularContainer.html new file mode 100644 index 00000000..9abffbf1 --- /dev/null +++ b/docs/PopularContainer.html @@ -0,0 +1,193 @@ + + + + + JSDoc: Class: PopularContainer + + + + + + + + + + +
+ +

Class: PopularContainer

+ + + + + + +
+ +
+ +

PopularContainer() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PopularContainer() → {React.Component}

+ + + + + + +
+

This component works as a container for all popular page components +and a repository the data fetched in

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Container represents the popular page

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Post.html b/docs/Post.html new file mode 100644 index 00000000..37077a62 --- /dev/null +++ b/docs/Post.html @@ -0,0 +1,1775 @@ + + + + + JSDoc: Class: Post + + + + + + + + + + +
+ +

Class: Post

+ + + + + + +
+ +
+ +

Post() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Post() → {React.Component}

+ + + + + + +
+

the post that appear in posts - saved - hidden - upvoted - downvotep taps

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
entity + + +object + + + +

an entity conatins all post informations

type + + +string + + + +

subTitle of the page

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Post

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

Post() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Post() → {React.Component}

+ + + + + + +
+

This component is the view of the post in home page.

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
title + + +string + + + +

Post title.

ownerType + + +string + + + +

Post owner type user or subreddit.

ownerIcon + + +string + + + +

Post owner icon.

ownerName + + +string + + + +

Post subreddit(post owner).

authorName + + +string + + + +

Post author.

flairText + + +string + + + +

Post flair text.

flairBackgroundColor + + +string + + + +

Post flair background color.

flairColor + + +string + + + +

Post flair color.

kind + + +string + + + +

Post kind (link, self, image, video).

images + + +Array.<string> + + + +

Array of sources of images

videos + + +Array.<string> + + + +

Array of sources of vidoes

votes + + +number + + + +

Number of post votes.

commentCount + + +number + + + +

Number of post comments.

text + + +string + + + +

Post text in case of "self" kind.

subreddit + + +boolean + + + +

to identify if post in home page or subreddit.

postVoteStatus + + +number + + + +

The last vote of the current user in this post.

isSaved + + +boolean + + + +

Is this post saved by the current user or not.

postId + + +number + + + +

The Id of the current post.

url + + +string + + + +

The post url.

nsfw + + +boolean + + + +

Whether the post is not safe for work or not.

spoiler + + +boolean + + + +

Whether the post is spoiler or not.

sharedFrom + + +Post + + + +

the Parent post of the current one.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Post

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

Post() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Post() → {React.Component}

+ + + + + + +
+

This component is the view of the post in home page.

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
title + + +string + + + +

Post title.

ownerType + + +string + + + +

Post owner type user or subreddit.

ownerIcon + + +string + + + +

Post owner icon.

ownerName + + +string + + + +

Post subreddit(post owner).

authorName + + +string + + + +

Post author.

flairText + + +string + + + +

Post flair text.

flairBackgroundColor + + +string + + + +

Post flair background color.

flairColor + + +string + + + +

Post flair color.

kind + + +string + + + +

Post kind (link, self, image, video).

images + + +Array.<string> + + + +

Array of sources of images

videos + + +Array.<string> + + + +

Array of sources of vidoes

votes + + +number + + + +

Number of post votes.

commentCount + + +number + + + +

Number of post comments.

text + + +string + + + +

Post text in case of "self" kind.

subreddit + + +boolean + + + +

to identify if post in home page or subreddit.

postVoteStatus + + +number + + + +

The last vote of the current user in this post.

isSaved + + +boolean + + + +

Is this post saved by the current user or not.

postId + + +number + + + +

The Id of the current post.

url + + +string + + + +

The post url.

nsfw + + +boolean + + + +

Whether the post is not safe for work or not.

spoiler + + +boolean + + + +

Whether the post is spoiler or not.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Post

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

Post() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Post() → {React.Component}

+ + + + + + +
+

Posts in search by posts

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Posts in search by posts
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostFooter.html b/docs/PostFooter.html new file mode 100644 index 00000000..aa867809 --- /dev/null +++ b/docs/PostFooter.html @@ -0,0 +1,518 @@ + + + + + JSDoc: Class: PostFooter + + + + + + + + + + +
+ +

Class: PostFooter

+ + + + + + +
+ +
+ +

PostFooter() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostFooter() → {React.Component}

+ + + + + + +
+

footer for a post conatining all icons

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subTitle + + +string + + + +

to check if a post is a spam or approved

numberOfComments + + +string + + + +

get number of comments in the post

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

PostFooter

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

PostFooter() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostFooter() → {React.Component}

+ + + + + + +
+

Footer of the post that contain all icons

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleExpand + + +function + + + +

pass the event to the parent to show the paragraph of the post

expand + + +state + + + +

pass a state to the parent to change the icon

entity + + +object + + + +

contains all info of the post

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

PostFooter

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostFooterList.html b/docs/PostFooterList.html new file mode 100644 index 00000000..188b5889 --- /dev/null +++ b/docs/PostFooterList.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: PostFooterList + + + + + + + + + + +
+ +

Class: PostFooterList

+ + + + + + +
+ +
+ +

PostFooterList() → {React.Component}

+ + +
+ + + +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostFooterListResponsive.html b/docs/PostFooterListResponsive.html new file mode 100644 index 00000000..5f455c04 --- /dev/null +++ b/docs/PostFooterListResponsive.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: PostFooterListResponsive + + + + + + + + + + +
+ +

Class: PostFooterListResponsive

+ + + + + + +
+ +
+ +

PostFooterListResponsive() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostFooterListResponsive() → {React.Component}

+ + + + + + +
+

resposive list of the post footer

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

PostFooterListResponsive

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostHeader.html b/docs/PostHeader.html new file mode 100644 index 00000000..d2076f97 --- /dev/null +++ b/docs/PostHeader.html @@ -0,0 +1,1388 @@ + + + + + JSDoc: Class: PostHeader + + + + + + + + + + +
+ +

Class: PostHeader

+ + + + + + +
+ +
+ +

PostHeader() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostHeader() → {React.Component}

+ + + + + + +
+

Header for a post

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subReddit + + +string + + + +

name of subReddit the post published in

nameuser + + +string + + + +

name of publisher

time + + +string + + + +

time of publishing the post

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

PostHeader

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

PostHeader() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostHeader() → {React.Component}

+ + + + + + +
+

Header of the post

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
nameUser + + +string + + + +

name of the currently loggedin user

Time + + +string + + + +

contains the time of the post

nameUser + + +string + + + +

contains the name of subreddit the post piblished in

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

PostHeader

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

PostHeader() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostHeader() → {React.Component}

+ + + + + + +
+

This component is the upper section of post

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
title + + +string + + + +

Post title.

ownerType + + +string + + + +

Post owner type user or subreddit.

ownerIcon + + +string + + + +

Post ownerName icon.

ownerName + + +string + + + +

Post subreddit(post ownerName).

authorName + + +string + + + +

Post authorName.

flairText + + +string + + + +

Post flair text.

flairBackgroundColor + + +string + + + +

Post flair background color.

flairColor + + +string + + + +

Post flair color.

subredit + + +boolean + + + +

to identify if post in home page or subreddit.

nsfw + + +boolean + + + +

Whether the post is not safe for work or not.

spoiler + + +boolean + + + +

Whether the post is spoiler or not.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Post header

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

PostHeader() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostHeader() → {React.Component}

+ + + + + + +
+

This component is the upper section of post

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
title + + +string + + + +

Post title.

ownerType + + +string + + + +

Post owner type user or subreddit.

ownerName + + +string + + + +

Post subreddit(post ownerName).

authorName + + +string + + + +

Post authorName.

flairText + + +string + + + +

Post flair text.

flairBackgroundColor + + +string + + + +

Post flair background color.

flairColor + + +string + + + +

Post flair color.

subredit + + +boolean + + + +

to identify if post in home page or subreddit.

nsfw + + +boolean + + + +

Whether the post is not safe for work or not.

spoiler + + +boolean + + + +

Whether the post is spoiler or not.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Post header

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostList.html b/docs/PostList.html new file mode 100644 index 00000000..32e47c97 --- /dev/null +++ b/docs/PostList.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Class: PostList + + + + + + + + + + +
+ +

Class: PostList

+ + + + + + +
+ +
+ +

PostList() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostList() → {React.Component}

+ + + + + + +
+

This component is the timeline (the container which contains all posts retrieved to be displayed)

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
posts + + +Array.<post> + + + +

post objects fetched

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

List of all posts

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostReactions.html b/docs/PostReactions.html new file mode 100644 index 00000000..f31f5c53 --- /dev/null +++ b/docs/PostReactions.html @@ -0,0 +1,382 @@ + + + + + JSDoc: Class: PostReactions + + + + + + + + + + +
+ +

Class: PostReactions

+ + + + + + +
+ +
+ +

PostReactions() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostReactions() → {React.Component}

+ + + + + + +
+

This component is the container of post reactions

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
votes + + +number + + + +

Number of post votes.

matchMd + + +boolean + + + +

check whether screen size is larger than meduim

matchSm + + +boolean + + + +

check whether screen size is larger than small

commentCount + + +number + + + +

Number of post comments.

postVoteStatus + + +number + + + +

The last vote of the current user in this post.

isSaved + + +boolean + + + +

Is this post saved by the current user or not.

postId + + +number + + + +

The Id of the current post.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

All post reactions.

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostSide.html b/docs/PostSide.html new file mode 100644 index 00000000..6b64f48f --- /dev/null +++ b/docs/PostSide.html @@ -0,0 +1,495 @@ + + + + + JSDoc: Class: PostSide + + + + + + + + + + +
+ +

Class: PostSide

+ + + + + + +
+ +
+ +

PostSide() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostSide() → {React.Component}

+ + + + + + +
+

sidebar of the post containing arrow up and down

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
points + + +number + + + +

number of points.

postVoteStatus + + +number + + + +

is the post is upvoted or sownvoted.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

PostSidebar

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

PostSide() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostSide() → {React.Component}

+ + + + + + +
+

Sidebar of the post conatining arrow up and down

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
points + + +number + + + +

number of votes on a post

postVoteStatus + + +number + + + +

is the post upvoted or down voted or none

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

PostSide

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostSubmission.html b/docs/PostSubmission.html new file mode 100644 index 00000000..93568720 --- /dev/null +++ b/docs/PostSubmission.html @@ -0,0 +1,633 @@ + + + + + JSDoc: Class: PostSubmission + + + + + + + + + + +
+ +

Class: PostSubmission

+ + + + + + +
+ +
+ +

PostSubmission() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostSubmission() → {React.Component}

+ + + + + + +
+

This component contains post and save draft buttons

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleSaveDraft + + +function + + + +

Hanlding save draft button

handlePost + + +function + + + +

Hanlding post submitting

readyToPost + + +boolean + + + +

Check whether the post button is disabled or not

sendReplies + + +boolean + + + +

Check whether the user need to be sent the post reply notifications or not.

handleSendReplies + + +function + + + +

Hanlding post reply notifications

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Container of buttons

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

PostSubmission() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostSubmission() → {React.Component}

+ + + + + + +
+

This component contains post and save draft buttons

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleSaveDraft + + +function + + + +

Hanlding save draft button

handlePost + + +function + + + +

Hanlding post submitting

readyToPost + + +boolean + + + +

Check whether the post button is disabled or not

sendReplies + + +boolean + + + +

Check whether the user need to be sent the post reply notifications or not.

handleSendReplies + + +function + + + +

Hanlding post reply notifications

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Container of buttons

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostTags.html b/docs/PostTags.html new file mode 100644 index 00000000..31ff441b --- /dev/null +++ b/docs/PostTags.html @@ -0,0 +1,587 @@ + + + + + JSDoc: Class: PostTags + + + + + + + + + + +
+ +

Class: PostTags

+ + + + + + +
+ +
+ +

PostTags() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostTags() → {React.Component}

+ + + + + + +
+

This component is post tags

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
spoiler + + +boolean + + + +

Check whether the post is spoiler or not.

hanldeSpoiler + + +function + + + +

function to handle click on spoiler button

nswf + + +boolean + + + +

Check whether the post is not safe for work or not.

hanldeNsfw + + +function + + + +

function to handle click on nsfw button

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Join button

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

PostTags() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostTags() → {React.Component}

+ + + + + + +
+

This component is post tags

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
spoiler + + +boolean + + + +

Check whether the post is spoiler or not.

hanldeSpoiler + + +function + + + +

function to handle click on spoiler button

nswf + + +boolean + + + +

Check whether the post is not safe for work or not.

hanldeNsfw + + +function + + + +

function to handle click on nsfw button

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Join button

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostTypes.html b/docs/PostTypes.html new file mode 100644 index 00000000..5587ac3c --- /dev/null +++ b/docs/PostTypes.html @@ -0,0 +1,267 @@ + + + + + JSDoc: Class: PostTypes + + + + + + + + + + +
+ +

Class: PostTypes

+ + + + + + +
+ +
+ +

PostTypes() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostTypes() → {React.Component}

+ + + + + + +
+

This component contains the tabs of post types

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
postType + + +function + + + +

Post type (text, image, video and url).

handlePostType + + +function + + + +

Hanlding post type.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

tabs of post types

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Posts.html b/docs/Posts.html new file mode 100644 index 00000000..cd4b9b67 --- /dev/null +++ b/docs/Posts.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Class: Posts + + + + + + + + + + +
+ +

Class: Posts

+ + + + + + +
+ +
+ +

Posts() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Posts() → {React.Component}

+ + + + + + +
+

Posts component represents an entity component

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
post + + +object + + + +

post entity

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Posts

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostsAndComments.html b/docs/PostsAndComments.html new file mode 100644 index 00000000..6b5a74c3 --- /dev/null +++ b/docs/PostsAndComments.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Class: PostsAndComments + + + + + + + + + + +
+ +

Class: PostsAndComments

+ + + + + + +
+ +
+ +

PostsAndComments() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostsAndComments() → {React.Component}

+ + + + + + +
+

Posts And Comments

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
redirect + + +function + + + +

redirect to home page

createCommunity + + +function + + + +

show create community form

SendData + + +function + + + +

send data to backend

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Posts And Comments
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostsClassification.html b/docs/PostsClassification.html new file mode 100644 index 00000000..ae6255e5 --- /dev/null +++ b/docs/PostsClassification.html @@ -0,0 +1,460 @@ + + + + + JSDoc: Class: PostsClassification + + + + + + + + + + +
+ +

Class: PostsClassification

+ + + + + + +
+ +
+ +

PostsClassification() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostsClassification() → {React.Component}

+ + + + + + +
+

Determine which type of posts should be fetched

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Tabs (each tab indicate the type of posts that will be fetched)

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(inner) handleChangeClass()

+ + + + + + +
+

this function handles change in post class

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleClick()

+ + + + + + +
+

this function set the active class of posts

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(inner) handleClickAway()

+ + + + + + +
+

this function handles click away from posts classification post

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostsFilteredTap.html b/docs/PostsFilteredTap.html new file mode 100644 index 00000000..ad3a4f9a --- /dev/null +++ b/docs/PostsFilteredTap.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Class: PostsFilteredTap + + + + + + + + + + +
+ +

Class: PostsFilteredTap

+ + + + + + +
+ +
+ +

PostsFilteredTap() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostsFilteredTap() → {React.Component}

+ + + + + + +
+

filtered taps (saved - hidden - upvoted - downvoted)

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
type + + +string + + + +

conatins the subtitle of the page to render correctly

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

PostsFilteredTap

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/PostsTap.html b/docs/PostsTap.html new file mode 100644 index 00000000..9b6ebae6 --- /dev/null +++ b/docs/PostsTap.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: PostsTap + + + + + + + + + + +
+ +

Class: PostsTap

+ + + + + + +
+ +
+ +

PostsTap() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new PostsTap() → {React.Component}

+ + + + + + +
+

posts tap in my profile

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

PostsTap

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ProfileHeader.html b/docs/ProfileHeader.html new file mode 100644 index 00000000..b78d5ee9 --- /dev/null +++ b/docs/ProfileHeader.html @@ -0,0 +1,387 @@ + + + + + JSDoc: Class: ProfileHeader + + + + + + + + + + +
+ +

Class: ProfileHeader

+ + + + + + +
+ +
+ +

ProfileHeader() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ProfileHeader() → {React.Component}

+ + + + + + +
+

ProfileHeader

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClick + + +function + + + +

to navigate to the subpage

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Header
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(inner) handleClick(subPage)

+ + + + + + +
+

this function to navigate between the taps

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subPage + + +string + + + +

the page to navigate to

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ProfileImage.html b/docs/ProfileImage.html new file mode 100644 index 00000000..27506cfc --- /dev/null +++ b/docs/ProfileImage.html @@ -0,0 +1,173 @@ + + + + + JSDoc: Class: ProfileImage + + + + + + + + + + +
+ +

Class: ProfileImage

+ + + + + + +
+ +
+ +

ProfileImage()

+ + +
+ +
+
+ + + + + + +

new ProfileImage()

+ + + + + + +
+
    +
  • ProfileImage
  • +
  • Edit Image and Banner in Seetings Page
  • +
+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ProfileInoformation.html b/docs/ProfileInoformation.html new file mode 100644 index 00000000..4229b6de --- /dev/null +++ b/docs/ProfileInoformation.html @@ -0,0 +1,320 @@ + + + + + JSDoc: Class: ProfileInoformation + + + + + + + + + + +
+ +

Class: ProfileInoformation

+ + + + + + +
+ +
+ +

ProfileInoformation(prefs)

+ + +
+ +
+
+ + + + + + +

new ProfileInoformation(prefs)

+ + + + + + +
+
    +
  • ProfileInoformation
  • +
  • Edit Display name and About people in Seetings Page
  • +
+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
prefs + + +Object + + + +

prefs of user

+ + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
setPrefs + + +function + + + +

set prefs of user

name + + +String + + + +

name of user

about + + +String + + + +

description of user

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ProfileMainContent.html b/docs/ProfileMainContent.html new file mode 100644 index 00000000..71659d59 --- /dev/null +++ b/docs/ProfileMainContent.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: ProfileMainContent + + + + + + + + + + +
+ +

Class: ProfileMainContent

+ + + + + + +
+ +
+ +

ProfileMainContent() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ProfileMainContent() → {React.Component}

+ + + + + + +
+

MainContent if the profile page

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClick + + +function + + + +

to navigate to the subpage

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • MainContent
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/RadioBtn.html b/docs/RadioBtn.html new file mode 100644 index 00000000..d0721b2c --- /dev/null +++ b/docs/RadioBtn.html @@ -0,0 +1,633 @@ + + + + + JSDoc: Class: RadioBtn + + + + + + + + + + +
+ +

Class: RadioBtn

+ + + + + + +
+ +
+ +

RadioBtn(props) → {React.Component}

+ + +
+ +
+
+ + + + + + +

new RadioBtn(props) → {React.Component}

+ + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
props + + +object + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

-radio button in pop up form

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

RadioBtn(props) → {React.Component}

+ + +
+ +
+
+ + + + + + +

new RadioBtn(props) → {React.Component}

+ + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
props + + +object + + + +

default value for radio buttom & myType to set it when change

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

-radio button in pop up form

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

RadioBtn(props) → {React.Component}

+ + +
+ +
+
+ + + + + + +

new RadioBtn(props) → {React.Component}

+ + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
props + + +object + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

-radio button in pop up form

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Reactions.html b/docs/Reactions.html new file mode 100644 index 00000000..07f48b57 --- /dev/null +++ b/docs/Reactions.html @@ -0,0 +1,313 @@ + + + + + JSDoc: Class: Reactions + + + + + + + + + + +
+ +

Class: Reactions

+ + + + + + +
+ +
+ +

Reactions() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Reactions() → {React.Component}

+ + + + + + +
+

This component is the container of reactions

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
flexDirection + + +string + + + +

The direction of reactions (vertical or horizontal).

votes + + +number + + + +

Number of post votes.

postId + + +number + + + +

The Id of the current post.

viewpost + + +boolean + + + +

To differentiate between post and view post.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Upvote and downvote only.

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/RedditPremium.html b/docs/RedditPremium.html new file mode 100644 index 00000000..462f5848 --- /dev/null +++ b/docs/RedditPremium.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: RedditPremium + + + + + + + + + + +
+ +

Class: RedditPremium

+ + + + + + +
+ +
+ +

RedditPremium() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new RedditPremium() → {React.Component}

+ + + + + + +
+

This component contains info about reddit premium.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Information about Premium version of reddit.

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/RemovePopUp.html b/docs/RemovePopUp.html new file mode 100644 index 00000000..e6c43c5e --- /dev/null +++ b/docs/RemovePopUp.html @@ -0,0 +1,345 @@ + + + + + JSDoc: Class: RemovePopUp + + + + + + + + + + +
+ +

Class: RemovePopUp

+ + + + + + +
+ +
+ +

RemovePopUp() → {React.Component}

+ + +
+ + + +
+ + + + + + + +
+ +
+ +

RemovePopUp() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new RemovePopUp() → {React.Component}

+ + + + + + +
+

remove the invitation of the moderator

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • remove the invitation of the moderator component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ResetPassword.html b/docs/ResetPassword.html new file mode 100644 index 00000000..4081880e --- /dev/null +++ b/docs/ResetPassword.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: ResetPassword + + + + + + + + + + +
+ +

Class: ResetPassword

+ + + + + + +
+ +
+ +

ResetPassword() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ResetPassword() → {React.Component}

+ + + + + + +
+

Component for Reset Password Page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

--ResetPassword Page Component

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Rules.html b/docs/Rules.html new file mode 100644 index 00000000..a36b1b4b --- /dev/null +++ b/docs/Rules.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: Rules + + + + + + + + + + +
+ +

Class: Rules

+ + + + + + +
+ +
+ +

Rules() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Rules() → {React.Component}

+ + + + + + +
+

About Rule

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Add Rule
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SavedTap.html b/docs/SavedTap.html new file mode 100644 index 00000000..c454cd56 --- /dev/null +++ b/docs/SavedTap.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: SavedTap + + + + + + + + + + +
+ +

Class: SavedTap

+ + + + + + +
+ +
+ +

SavedTap() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SavedTap() → {React.Component}

+ + + + + + +
+

Saved taps

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

PostsFilteredTap

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SearchBar.html b/docs/SearchBar.html new file mode 100644 index 00000000..f183d1d3 --- /dev/null +++ b/docs/SearchBar.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: SearchBar + + + + + + + + + + +
+ +

Class: SearchBar

+ + + + + + +
+ +
+ +

SearchBar() → {React.Component}

+ + +
+ +
+
+ + + + + + + + + + + + + +
+

the search bar

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
childToParent + + +function + + + +

it is a function state to pass the query from the child (search bar) to its parent (user management list)

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • the search bar component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SearchByComments.html b/docs/SearchByComments.html new file mode 100644 index 00000000..1bbf6704 --- /dev/null +++ b/docs/SearchByComments.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: SearchByComments + + + + + + + + + + +
+ +

Class: SearchByComments

+ + + + + + +
+ +
+ +

SearchByComments() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SearchByComments() → {React.Component}

+ + + + + + +
+

Search by comments container

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Search by comments container
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SearchByCommunity.html b/docs/SearchByCommunity.html new file mode 100644 index 00000000..e9065a07 --- /dev/null +++ b/docs/SearchByCommunity.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: SearchByCommunity + + + + + + + + + + +
+ +

Class: SearchByCommunity

+ + + + + + +
+ +
+ +

SearchByCommunity() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SearchByCommunity() → {React.Component}

+ + + + + + +
+

Search by communities container

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Search by communities container
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SearchByPeople.html b/docs/SearchByPeople.html new file mode 100644 index 00000000..fcfbc711 --- /dev/null +++ b/docs/SearchByPeople.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: SearchByPeople + + + + + + + + + + +
+ +

Class: SearchByPeople

+ + + + + + +
+ +
+ +

SearchByPeople() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SearchByPeople() → {React.Component}

+ + + + + + +
+

Search by people container

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Search by people container
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SearchByPosts.html b/docs/SearchByPosts.html new file mode 100644 index 00000000..2c4d58e9 --- /dev/null +++ b/docs/SearchByPosts.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: SearchByPosts + + + + + + + + + + +
+ +

Class: SearchByPosts

+ + + + + + +
+ +
+ +

SearchByPosts() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SearchByPosts() → {React.Component}

+ + + + + + +
+

Search by posts container

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Search by posts container
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SearchField.html b/docs/SearchField.html new file mode 100644 index 00000000..a1286883 --- /dev/null +++ b/docs/SearchField.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: SearchField + + + + + + + + + + +
+ +

Class: SearchField

+ + + + + + +
+ +
+ +

SearchField() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SearchField() → {React.Component}

+ + + + + + +
+

SearchField Sign Navbar

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

the search bar in the navbar.

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SearchHeader.html b/docs/SearchHeader.html new file mode 100644 index 00000000..4daed775 --- /dev/null +++ b/docs/SearchHeader.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: SearchHeader + + + + + + + + + + +
+ +

Class: SearchHeader

+ + + + + + +
+ +
+ +

SearchHeader() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SearchHeader() → {React.Component}

+ + + + + + +
+

Search type in search by posts

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Search type in search by posts
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SearchResultBar.html b/docs/SearchResultBar.html new file mode 100644 index 00000000..102f807d --- /dev/null +++ b/docs/SearchResultBar.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Class: SearchResultBar + + + + + + + + + + +
+ +

Class: SearchResultBar

+ + + + + + +
+ +
+ +

SearchResultBar() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SearchResultBar() → {React.Component}

+ + + + + + +
+

the whole page of no result that appears when try to seach on a user in user managment section in moderatio page

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
resultNumber + + +string + + + +

the number of results from the query after search

filteredData + + +object + + + +

the result data after searching

childToParent + + +function + + + +

a function to pass result data from child to parent

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • no result page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SettingsAccount.html b/docs/SettingsAccount.html new file mode 100644 index 00000000..add1d71d --- /dev/null +++ b/docs/SettingsAccount.html @@ -0,0 +1,271 @@ + + + + + JSDoc: Class: SettingsAccount + + + + + + + + + + +
+ +

Class: SettingsAccount

+ + + + + + +
+ +
+ +

SettingsAccount()

+ + +
+ +
+
+ + + + + + +

new SettingsAccount()

+ + + + + + +
+
    +
  • SettingsAccount
  • +
  • Change Email and password in settings page
  • +
+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
setPrefs + + +function + + + +

set prefs of user

prefs + + +Object + + + +

prefs of user

data + + +Object + + + +

data from fetch

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SettingsFeed.html b/docs/SettingsFeed.html new file mode 100644 index 00000000..5b81b155 --- /dev/null +++ b/docs/SettingsFeed.html @@ -0,0 +1,271 @@ + + + + + JSDoc: Class: SettingsFeed + + + + + + + + + + +
+ +

Class: SettingsFeed

+ + + + + + +
+ +
+ +

SettingsFeed()

+ + +
+ +
+
+ + + + + + +

new SettingsFeed()

+ + + + + + +
+
    +
  • SettingsFeed
  • +
  • Change Adult content and Autoplay media in settings page
  • +
+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
setPrefs + + +function + + + +

set prefs of user

prefs + + +Object + + + +

prefs of user

data + + +Object + + + +

data from fetch

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SettingsHeader.html b/docs/SettingsHeader.html new file mode 100644 index 00000000..b9a55a45 --- /dev/null +++ b/docs/SettingsHeader.html @@ -0,0 +1,173 @@ + + + + + JSDoc: Class: SettingsHeader + + + + + + + + + + +
+ +

Class: SettingsHeader

+ + + + + + +
+ +
+ +

SettingsHeader()

+ + +
+ +
+
+ + + + + + +

new SettingsHeader()

+ + + + + + +
+
    +
  • SettingsHeader
  • +
  • Head of Settings
  • +
+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SettingsPrivacy.html b/docs/SettingsPrivacy.html new file mode 100644 index 00000000..e72d8561 --- /dev/null +++ b/docs/SettingsPrivacy.html @@ -0,0 +1,173 @@ + + + + + JSDoc: Class: SettingsPrivacy + + + + + + + + + + +
+ +

Class: SettingsPrivacy

+ + + + + + +
+ +
+ +

SettingsPrivacy()

+ + +
+ +
+
+ + + + + + +

new SettingsPrivacy()

+ + + + + + +
+
    +
  • SettingsPrivacy
  • +
  • Edit block list in Settings page
  • +
+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SettingsProfile.html b/docs/SettingsProfile.html new file mode 100644 index 00000000..4146bec7 --- /dev/null +++ b/docs/SettingsProfile.html @@ -0,0 +1,248 @@ + + + + + JSDoc: Class: SettingsProfile + + + + + + + + + + +
+ +

Class: SettingsProfile

+ + + + + + +
+ +
+ +

SettingsProfile()

+ + +
+ +
+
+ + + + + + +

new SettingsProfile()

+ + + + + + +
+
    +
  • SettingsProfile
  • +
  • Edit NSFW and Allow people to follow you in Seetings Page
  • +
+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
data + + +String + + + +

data from fetch

prefs + + +Object + + + +

prefs of user

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SideBar.html b/docs/SideBar.html new file mode 100644 index 00000000..72f1e892 --- /dev/null +++ b/docs/SideBar.html @@ -0,0 +1,553 @@ + + + + + JSDoc: Class: SideBar + + + + + + + + + + +
+ +

Class: SideBar

+ + + + + + +
+ +
+ +

SideBar() → {React.Component}

+ + +
+ +
+
+ + + + + + + + + + + + + +
+

Search by posts sidebar

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

-Search by posts sidebar

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

SideBar() → {React.Component}

+ + +
+ +
+
+ + + + + + + + + + + + + +
+

This component works as a container for the right half components +like communities in home page

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
children + + +React.Component + + + +

Components which will be wrapped in sidebar

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Container represents its children

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

SideBar() → {React.Component}

+ + +
+ +
+
+ + + + + + + + + + + + + +
+

SideBar for subreddit

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • SideBar for subreddit
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Sidebar_.html b/docs/Sidebar_.html new file mode 100644 index 00000000..49f7a8b6 --- /dev/null +++ b/docs/Sidebar_.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: Sidebar + + + + + + + + + + +
+ +

Class: Sidebar

+ + + + + + +
+ +
+ +

Sidebar() → {React.Component}

+ + +
+ +
+
+ + + + + + + + + + + + + +
+

sidebar in profile containing the userinfo and communities you are a moderator of

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Sidebar

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SignNavbar.html b/docs/SignNavbar.html new file mode 100644 index 00000000..91aeeb0b --- /dev/null +++ b/docs/SignNavbar.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: SignNavbar + + + + + + + + + + +
+ +

Class: SignNavbar

+ + + + + + +
+ +
+ +

SignNavbar() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SignNavbar() → {React.Component}

+ + + + + + +
+

SNavbar

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

main body of navbar in signed out mode

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SignUp.html b/docs/SignUp.html new file mode 100644 index 00000000..cab94248 --- /dev/null +++ b/docs/SignUp.html @@ -0,0 +1,418 @@ + + + + + JSDoc: Class: SignUp + + + + + + + + + + +
+ +

Class: SignUp

+ + + + + + +
+ +
+ +

SignUp() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SignUp() → {React.Component}

+ + + + + + +
+

SignUp Page Main Componnet with 2 view one for the Email and the Other for the userName

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

SignUp Page

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

SignUp(param0, param1) → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SignUp(param0, param1) → {React.Component}

+ + + + + + +
+

SignUp popUp

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
param0 + + +setUserNamePage + + + +
param1 + + +setEmail + + + +

used for animate the email input field

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

sign up popup different component +main body of sign up popup

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SignUpPopUpUserName.html b/docs/SignUpPopUpUserName.html new file mode 100644 index 00000000..c0156e34 --- /dev/null +++ b/docs/SignUpPopUpUserName.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: SignUpPopUpUserName + + + + + + + + + + +
+ +

Class: SignUpPopUpUserName

+ + + + + + +
+ +
+ +

SignUpPopUpUserName() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SignUpPopUpUserName() → {React.Component}

+ + + + + + +
+

SignUp UseerName popUp

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Main Body of SignUp UseerName PopUp
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SignUpUsername.html b/docs/SignUpUsername.html new file mode 100644 index 00000000..cbd951b8 --- /dev/null +++ b/docs/SignUpUsername.html @@ -0,0 +1,359 @@ + + + + + JSDoc: Class: SignUpUsername + + + + + + + + + + +
+ +

Class: SignUpUsername

+ + + + + + +
+ +
+ +

SignUpUsername() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SignUpUsername() → {React.Component}

+ + + + + + +
+

SignUp Username and Password Page View

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
--setUserNamePage + + +SetFunction + + + +

setView to Email Page on Back Button Click

--email + + +object + + + +

setView to Email Page on Back Button Click

--userName + + +object + + + +

userName to SignUp with

--setUserName + + +function + + + +

to set UserName

--password + + +object + + + +

password to SignUp with

--setPassword + + +function + + + +

to set password

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

UserName and Password Form

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SimilarTopics.html b/docs/SimilarTopics.html new file mode 100644 index 00000000..52f244da --- /dev/null +++ b/docs/SimilarTopics.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: SimilarTopics + + + + + + + + + + +
+ +

Class: SimilarTopics

+ + + + + + +
+ +
+ +

SimilarTopics() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SimilarTopics() → {React.Component}

+ + + + + + +
+

similar topics of the explore page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • similar topics component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SocialLinks.html b/docs/SocialLinks.html new file mode 100644 index 00000000..b87a538b --- /dev/null +++ b/docs/SocialLinks.html @@ -0,0 +1,612 @@ + + + + + JSDoc: Class: SocialLinks + + + + + + + + + + +
+ +

Class: SocialLinks

+ + + + + + +
+ +
+ +

SocialLinks(onClose, settings, link)

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
onClose + + +function + + + +

function when close window

settings + + +Boolean + + + +

bool too know if we in settings page or not

link + + +Object + + + +

data of plateform we choose in settings

+ + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
links + + +Array + + + +

Array of links

openDialog2 + + +Boolean + + + +

bool to choose which window open

platform + + +Object + + + +

data of plateform choose

condition + + +Boolean + + + +

condition if valid we submit or not

text + + +string + + + +

url or user name

error + + +Boolean + + + +

true if we have invalid domin or username

msg + + +string + + + +

massage if we have error

url + + +Boolean + + + +

true if plate form have link and display name

edit + + +Boolean + + + +

true if it's first time to edit text

title + + +string + + + +

title of link

handleOpenPlatform + + +function + + + +

function to open window to edit data platedform

handleClose + + +function + + + +

function to close window to edit data platedform

checkSubmission + + +function + + + +

function to check data before submit

handelchange + + +function + + + +

function to handle input from user

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SocialLinksSettings.html b/docs/SocialLinksSettings.html new file mode 100644 index 00000000..188c51e4 --- /dev/null +++ b/docs/SocialLinksSettings.html @@ -0,0 +1,320 @@ + + + + + JSDoc: Class: SocialLinksSettings + + + + + + + + + + +
+ +

Class: SocialLinksSettings

+ + + + + + +
+ +
+ +

SocialLinksSettings(prefs, setPrefs)

+ + +
+ +
+
+ + + + + + +

new SocialLinksSettings(prefs, setPrefs)

+ + + + + + +
+
    +
  • ProfileInoformation
  • +
  • Edit Display name and About people in Seetings Page
  • +
+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
prefs + + +Object + + + +

prefs of user

setPrefs + + +function + + + +

set prefs of user

+ + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
open + + +Boolean + + + +

Boolean to open or close popup

handleDelete + + +function + + + +

function to delete social link

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Subreddits.html b/docs/Subreddits.html new file mode 100644 index 00000000..d61f647f --- /dev/null +++ b/docs/Subreddits.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Class: Subreddits + + + + + + + + + + +
+ +

Class: Subreddits

+ + + + + + +
+ +
+ +

Subreddits() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Subreddits() → {React.Component}

+ + + + + + +
+

Search by community

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleJoin + + +function + + + +

send join to backend

handleMouseIn + + +function + + + +

when hover set buttom value to leave

handleMouseOut + + +function + + + +

when out of hover set button value to joined

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Search by community
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/SubredditsMenu.html b/docs/SubredditsMenu.html new file mode 100644 index 00000000..ee173e2e --- /dev/null +++ b/docs/SubredditsMenu.html @@ -0,0 +1,633 @@ + + + + + JSDoc: Class: SubredditsMenu + + + + + + + + + + +
+ +

Class: SubredditsMenu

+ + + + + + +
+ +
+ +

SubredditsMenu() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SubredditsMenu() → {React.Component}

+ + + + + + +
+

This component contains the menu of subreddit that the use can post in

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
setCommunityToPostIn + + +function + + + +

Hanlding post owner (ID).

setOwnerType + + +function + + + +

Hanlding post owner type (subreddit or user).

subredditIcon + + +string + + + +

Subreddit icon.

subredditName + + +string + + + +

Subreddit name.

ownerType + + +string + + + +

to know if the type of the owner is User or Subreddit

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Container of subreddit menu

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

SubredditsMenu() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SubredditsMenu() → {React.Component}

+ + + + + + +
+

This component contains the menu of subreddit that the use can post in

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
setCommunityToPostIn + + +function + + + +

Hanlding post owner (ID).

setOwnerType + + +function + + + +

Hanlding post owner type (subreddit or user).

subredditIcon + + +string + + + +

Subreddit icon.

subredditName + + +string + + + +

Subreddit name.

ownerType + + +string + + + +

to know if the type of the owner is User or Subreddit

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Container of subreddit menu

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Suggestions.html b/docs/Suggestions.html new file mode 100644 index 00000000..44ebe61e --- /dev/null +++ b/docs/Suggestions.html @@ -0,0 +1,545 @@ + + + + + JSDoc: Class: Suggestions + + + + + + + + + + +
+ +

Class: Suggestions

+ + + + + + +
+ +
+ +

Suggestions() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Suggestions() → {React.Component}

+ + + + + + +
+

Search by community entity in sidebar

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleJoin + + +function + + + +

send join to backend

handleMouseIn + + +function + + + +

when hover set buttom value to leave

handleMouseOut + + +function + + + +

when out of hover set button value to joined

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Search by community entity in sidebar
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

Suggestions() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Suggestions() → {React.Component}

+ + + + + + +
+

people in sidebar entity

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleJoin + + +function + + + +

send follow to backend

handleMouseIn + + +function + + + +

when hover set buttom value to unfollow

handleMouseOut + + +function + + + +

when out of hover set button value to follow

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • people in sidebar entity
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/ThirdParty.html b/docs/ThirdParty.html new file mode 100644 index 00000000..70935861 --- /dev/null +++ b/docs/ThirdParty.html @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: ThirdParty + + + + + + + + + + +
+ +

Class: ThirdParty

+ + + + + + +
+ +
+ +

ThirdParty() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ThirdParty() → {React.Component}

+ + + + + + +
+

Third Party [Google and Facebook] Components

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Continue with google and Facebook
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/UnmutePopUp.html b/docs/UnmutePopUp.html new file mode 100644 index 00000000..fef3f146 --- /dev/null +++ b/docs/UnmutePopUp.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: UnmutePopUp + + + + + + + + + + +
+ +

Class: UnmutePopUp

+ + + + + + +
+ +
+ +

UnmutePopUp() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new UnmutePopUp() → {React.Component}

+ + + + + + +
+

Unmute Popup

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
username + + +string + + + +

the username of the muted user

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • unmute popup component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/UserInfo.html b/docs/UserInfo.html new file mode 100644 index 00000000..aa32614c --- /dev/null +++ b/docs/UserInfo.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: UserInfo + + + + + + + + + + +
+ +

Class: UserInfo

+ + + + + + +
+ +
+ +

UserInfo() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new UserInfo() → {React.Component}

+ + + + + + +
+

UserInfo Box in sidebar containing all info of a user

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

UserInfo

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/UserList.html b/docs/UserList.html new file mode 100644 index 00000000..159217b2 --- /dev/null +++ b/docs/UserList.html @@ -0,0 +1,345 @@ + + + + + JSDoc: Class: UserList + + + + + + + + + + +
+ +

Class: UserList

+ + + + + + +
+ +
+ +

UserList() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new UserList() → {React.Component}

+ + + + + + +
+

UserList

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

the User list which is the right lish in logged in navbar.

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

UserList() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new UserList() → {React.Component}

+ + + + + + +
+

UserList

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

the User list which is the right lish in logged in navbar.

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/Username.html b/docs/Username.html new file mode 100644 index 00000000..8d64b551 --- /dev/null +++ b/docs/Username.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Class: Username + + + + + + + + + + +
+ +

Class: Username

+ + + + + + +
+ +
+ +

Username() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new Username() → {React.Component}

+ + + + + + +
+

username input field for all user management serction popups

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
placeholder + + +string + + + +

determine the string that appear in the user input field

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • username input field component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/components_All_AllContainer_AllContainer.jsx.html b/docs/components_All_AllContainer_AllContainer.jsx.html new file mode 100644 index 00000000..ed53a999 --- /dev/null +++ b/docs/components_All_AllContainer_AllContainer.jsx.html @@ -0,0 +1,107 @@ + + + + + JSDoc: Source: components/All/AllContainer/AllContainer.jsx + + + + + + + + + + +
+ +

Source: components/All/AllContainer/AllContainer.jsx

+ + + + + + +
+
+
import { useMediaQuery, useTheme } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import MainContent from '../../MainContent/MainContent';
+import { MainContainer, OuterContainer } from '../../HomePage/HomePageContainer/styles';
+import SideBar from '../../SideBar/SideBar';
+import RedditPremium from '../../HomePage/HomePageContainer/RedditPremium/RedditPremium';
+import PersonalReddit from '../../HomePage/HomePageContainer/PersonalReddit/PersonalReddit';
+import HomePageFooter from '../../HomePage/HomePageContainer/HomePageFooter/HomePageFooter';
+import PostsClassification from '../../HomePage/HomePageContainer/PostsClassification/PostsClassification';
+import BackToTop from '../../BackToTop/BackToTop';
+import PostList from '../../HomePage/HomePageContainer/PostList/PostList';
+import allPageServer from './allPageServer';
+import cleanPage from '../../../utils/cleanPage';
+
+/**
+ * This component works as a container for all popular page components
+ * and a repository the data fetched in
+ *
+ * @component PopularContainer
+ * @returns {React.Component} Container represents the popular page
+ */
+function AllContainer() {
+  const { postClass } = useParams();
+  // variables
+  const theme = useTheme();
+  const match = useMediaQuery(theme.breakpoints.up('md'));
+
+  // states
+  const [posts, postsError] = allPageServer(postClass);
+  cleanPage();
+  return (
+    <OuterContainer>
+      <MainContainer>
+        <MainContent width={640}>
+          <PostsClassification allOrPopular="r/all/" />
+          {!postsError ? (posts && <PostList posts={posts} />) : 'error in fetching posts'}
+        </MainContent>
+        {match
+        && (
+        <SideBar>
+          <RedditPremium />
+          <PersonalReddit
+            title="r/all"
+            paragraph="The most active posts from all of Reddit. Come here to see new posts rising and be a part of the conversation."
+            image="https://www.redditstatic.com/desktop2x/img/id-cards/banner@2x.png"
+          />
+          <HomePageFooter />
+          <BackToTop />
+        </SideBar>
+        )}
+      </MainContainer>
+    </OuterContainer>
+  );
+}
+
+export default AllContainer;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_Email_Email.jsx.html b/docs/components_Authentication_Email_Email.jsx.html new file mode 100644 index 00000000..e965de08 --- /dev/null +++ b/docs/components_Authentication_Email_Email.jsx.html @@ -0,0 +1,135 @@ + + + + + JSDoc: Source: components/Authentication/Email/Email.jsx + + + + + + + + + + +
+ +

Source: components/Authentication/Email/Email.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+
+// Compoenets
+import ReCAPTCHA from 'react-google-recaptcha';
+
+// styles
+import {
+  FirstPartyContainer, RedditTextField, RedditLoadingButton,
+} from '../styles';
+
+// scripts
+import { checkEmail } from '../authenticationServer';
+
+// env Variables
+const { REACT_APP_SITEKEY } = process.env;
+
+/**
+ * Email Compoenet with ReCAPTCHA if required
+ *
+ * @component
+ * @property {object} --email email Taken from input field
+ * @property {function} --setEmail set email object
+ * @property {function} --onSubmitFn On Submit form
+ * @property {boolean} --loading loading prop ofr RedditLoadingButton
+ * @property {string} --width width of the form
+ * @property {string} --buttonText text on the Submit button
+ * @property {string} --fieldText text on the input field
+ * @property {string} --btnWidth submit button width
+ * @property {bool} --recaptcha if we ReCAPTCHA is required on not
+ * @property {function} --setVerified to set that recaptcha is verified
+ * @property {boolean} --disabled to disabled prop ofr RedditLoadingButton
+ * @returns {React.Component} Email Form
+ */
+function Email({
+  email, setEmail, onSubmitFn, loading, width, buttonText, fieldText, btnWidth, recaptcha, setVerified, disabled,
+}) {
+  const [defaultEmailValue, setdefaultEmailValue] = useState(email?.input);
+  const [recaptchaState, setrecaptchaState] = useState(false);
+
+  return (
+    // right value emailon submit in case that we have made any change in input field
+    // in case no change the value there is wrong :) but the view here is true
+    <FirstPartyContainer width={width} onSubmit={(e) => { e.preventDefault(); checkEmail(email.input, setEmail); onSubmitFn(); }} noValidate data-testid="SignUpEmail-test">
+      <RedditTextField
+        label={fieldText}
+        variant="filled"
+        required
+        InputProps={{
+          endAdornment: (
+            email?.icon
+          ),
+          disableUnderline: true,
+        }}
+        clr={email?.color}
+        onBlur={() => { if (recaptcha) setrecaptchaState(true); }}
+        onChange={(e) => {
+          if (recaptcha) setrecaptchaState(true);
+          setEmail((prevState) => ({
+            ...prevState,
+            input: e.target.value.trim(),
+          }));
+          checkEmail(e.target.value.trim(), setEmail);
+          setdefaultEmailValue(e.target.value.trim());
+        }}
+        helperText={email?.error}
+        value={defaultEmailValue || ''}
+      />
+      <RedditLoadingButton type="submit" loading={loading} data-testid="email-btn-test" width={btnWidth} disabled={disabled}>
+        {buttonText}
+      </RedditLoadingButton>
+      {recaptchaState ? (
+        <ReCAPTCHA
+          sitekey={REACT_APP_SITEKEY}
+          onExpired={() => setVerified(false)}
+          onChange={() => setVerified(true)}
+          size="normal"
+          sx={{ width: '320px' }}
+        />
+      )
+        : null}
+    </FirstPartyContainer>
+  );
+}
+export default Email;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_FirstParty_FirstParty.jsx.html b/docs/components_Authentication_FirstParty_FirstParty.jsx.html new file mode 100644 index 00000000..0d7dd0f1 --- /dev/null +++ b/docs/components_Authentication_FirstParty_FirstParty.jsx.html @@ -0,0 +1,146 @@ + + + + + JSDoc: Source: components/Authentication/FirstParty/FirstParty.jsx + + + + + + + + + + +
+ +

Source: components/Authentication/FirstParty/FirstParty.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+import { useCookies } from 'react-cookie';
+
+// mui components
+import { Typography } from '@mui/material';
+
+// styles
+import { FirstPartyContainer } from './styles';
+import { RedditLoadingButton, RedditTextField } from '../styles';
+import theme, { fonts } from '../../../styles/theme';
+
+// servers
+
+import { checkUserName, logIn } from './firstpartyServer';
+
+/**
+ * Form for Logging in by username and passsword
+ *
+ * @component
+ * @returns {React.Component} First Party Form
+ */
+function FirstParty() {
+  // useState
+  const [userName, setUserName] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+  const [password, setPassword] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+  const [buttonTxt, setButtonText] = useState('Log In');
+  const [loading, setLoading] = useState(false);
+  const [disabled, setDisabled] = useState(false);
+  const [redirectCaption, setRedirectCaption] = useState(false);
+
+  // useCookies
+  // eslint-disable-next-line no-unused-vars
+  const [cookies, setCookies, removeCookie] = useCookies(['redditUser']);
+  return (
+
+    <FirstPartyContainer width="290px" onSubmit={(e) => { logIn(e, setLoading, userName, password, setPassword, setButtonText, setDisabled, setRedirectCaption, setCookies, removeCookie, setUserName); }} data-testid="FirstParty-test">
+
+      <RedditTextField
+        label="Username"
+        variant="filled"
+        type="text"
+        required
+        InputProps={{
+          endAdornment: (
+            userName.icon
+          ),
+          disableUnderline: true,
+        }}
+        clr={userName.color}
+        onChange={(e) => {
+          setUserName((prevState) => ({
+            ...prevState,
+            input: e.target.value.trim(),
+          }));
+          checkUserName(e.target.value.trim(), setUserName);
+        }}
+        helperText={userName.error}
+        data-testid="UserName-FirstParty-test"
+      />
+      <RedditTextField
+        label="Password"
+        variant="filled"
+        type="password"
+        required
+        InputProps={{
+          endAdornment: (
+            password.icon
+          ),
+          disableUnderline: true,
+        }}
+        clr={password.color}
+        onChange={(e) => setPassword((prevState) => ({
+          ...prevState,
+          input: e.target.value.trim(),
+        }))}
+        data-testid="Password-FirstParty-test"
+      />
+
+      <RedditLoadingButton type="submit" loading={loading} data-testid="login-btn-test" disabled={disabled}>
+        {buttonTxt}
+      </RedditLoadingButton>
+
+      {redirectCaption
+        ? <Typography color="primary" fontSize="12px" fontFamily={fonts['system-ui']} fontWeight="600" margin="10px 0px">You are now logged in. You will soon be redirected</Typography>
+        : null}
+    </FirstPartyContainer>
+
+  );
+}
+
+export default FirstParty;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_FirstParty_firstpartyServer.js.html b/docs/components_Authentication_FirstParty_firstpartyServer.js.html new file mode 100644 index 00000000..ef170bb0 --- /dev/null +++ b/docs/components_Authentication_FirstParty_firstpartyServer.js.html @@ -0,0 +1,189 @@ + + + + + JSDoc: Source: components/Authentication/FirstParty/firstpartyServer.js + + + + + + + + + + +
+ +

Source: components/Authentication/FirstParty/firstpartyServer.js

+ + + + + + +
+
+
// mui components
+import DoneIcon from '@mui/icons-material/Done';
+
+// services
+import axios from '../../../services/instance';
+
+// styles
+import { wrongIcon, rightIcon } from '../styles';
+
+import theme from '../../../styles/theme';
+
+// scripts
+import { redditCookie } from '../authenticationServer';
+import { redirectHome } from '../../../utils/Redirect';
+
+/**
+*
+* Function to check if length of provided string 3-20 accordingly change color and mesaages of username input field
+* @param {string} username  -username to check on
+* @returns void
+*/
+export const checkUserName = (username, setUserName) => {
+  // console.log(userName); // late
+  // Check Username bwteen 3-20 characters
+  if (username.length < 3 || username.length > 20) {
+    setUserName((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'Username must be between 3 and 20 characters',
+    }));
+    return;
+  }
+  // else Valid
+  setUserName((prevState) => ({
+    ...prevState,
+    color: theme.palette.primary.main,
+    icon: rightIcon,
+    error: null,
+  }));
+};
+
+/**
+*
+* Function Calls /users/login endpoint to Redirect to Home Page or Invalid so Error Messages Appear
+* @param {event} event -Onsubmit of the form
+* @returns void
+*/
+export const logIn = async (
+  event,
+  setLoading,
+  userName,
+  password,
+  setPassword,
+  setButtonText,
+  setDisabled,
+  setRedirectCaption,
+  setCookies,
+  removeCookie,
+  setUserName,
+  popUp = false,
+  // eslint-disable-next-line no-unused-vars
+  handleClose = null,
+) => {
+  event.preventDefault();
+  // console.log(userName);// Not Late
+  // console.log(password);// Not Late
+
+  // Add cookie to localStorage
+  setLoading(true);
+  if (userName.error != null && userName.error !== 'Incorrect username or password') {
+    setLoading(false);
+    return;
+  }
+
+  // Case of previous trial was error
+  setPassword((prevState) => ({
+    ...prevState,
+    color: theme.palette.neutral.main,
+    icon: null,
+    error: null,
+  }));
+
+  setUserName((prevState) => ({
+    ...prevState,
+    color: theme.palette.neutral.main,
+    icon: null,
+    error: null,
+  }));
+
+  // API Call
+  // console.log(userName.input);
+  axios.post('/users/login', {
+    userName: userName.input, password: password.input,
+  }).then(async (response) => {
+    console.log('login Response', response);
+    if (response.status === 200 || response.status === 201) {
+      setLoading(false);
+      setButtonText(<DoneIcon />);
+      setDisabled(true);
+      setRedirectCaption(true);
+      // Add Reddit Cookie
+      if (popUp === false) {
+        console.log('popup');
+        redditCookie(setCookies, removeCookie);
+        redirectHome(1000);
+      } else {
+        // PopUp window
+        const interval = setInterval(() => {
+          handleClose();
+          redditCookie(setCookies, removeCookie);
+          clearInterval(interval);
+        }, 1000);
+      }
+    }
+  }).catch((error) => {
+    setLoading(false);
+    console.log(error);
+    if (error.response.status === 404 || error.response.status === 400) {
+      // Invlaid Username or password
+      // update username and password states
+      setUserName((prevState) => ({
+        ...prevState,
+        color: theme.palette.error.main,
+        icon: wrongIcon,
+        error: 'Incorrect username or password',
+      }));
+      setPassword((prevState) => ({
+        ...prevState,
+        color: theme.palette.error.main,
+        icon: wrongIcon,
+        error: null,
+      }));
+    } else {
+      console.log(error.response.data.errorMessage);
+    }
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_ForgetPassword_ForgetPassword.jsx.html b/docs/components_Authentication_ForgetPassword_ForgetPassword.jsx.html new file mode 100644 index 00000000..5b526659 --- /dev/null +++ b/docs/components_Authentication_ForgetPassword_ForgetPassword.jsx.html @@ -0,0 +1,223 @@ + + + + + JSDoc: Source: components/Authentication/ForgetPassword/ForgetPassword.jsx + + + + + + + + + + +
+ +

Source: components/Authentication/ForgetPassword/ForgetPassword.jsx

+ + + + + + +
+
+
import { useEffect, useState } from 'react';
+import { useCookies } from 'react-cookie';
+
+// mui components
+import { Typography } from '@mui/material';
+
+// componnets
+import AuthenticationHeader from '../AuthenticationHeader/AuthenticationHeader';
+import LoadingPage from '../LoadingPage/LoadingPage';
+
+// styles
+import {
+  AuthenticationBody, FirstPartyContainer, StyledLink, RedditTextField,
+  RedditLoadingButton,
+} from '../styles';
+import theme, { fonts } from '../../../styles/theme';
+
+// server
+import { checkUserName, recoverPassword } from './ForgetPasswordServer';
+
+// scripts
+import { redditCookie, checkEmail } from '../authenticationServer';
+
+// environment variables
+// const { REACT_APP_ENV } = process.env;
+
+/**
+ * Component for Forget Password Page
+ *
+ * @component
+ * @returns {React.Component} --ForgetPassword Page Component
+ */
+function ForgetPassword() {
+  // states
+  const [remeberMe, setremeberMe] = useState(false);
+  const [loading, setLoading] = useState(false);
+  const [buttonText, setbuttonText] = useState('Reset Password');
+  const [disabled, setDisabled] = useState(false);
+  const [redirectCaption, setRedirectCaption] = useState(false);
+  const [userName, setUserName] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+  const [email, setEmail] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+
+  // cookies
+  const [cookies, setCookies, removeCookie] = useCookies(['redditUser']);
+
+  // useEffect
+  useEffect(() => {
+    // Check on Cookies
+    // developememt
+    /// Ask if this user already loggied in the back
+    redditCookie(setCookies, removeCookie);
+    if (cookies.redditUser !== undefined) {
+      // production
+      // Update Cookie
+      // redditCookie(setCookies);
+      // check on Reddit cookie
+      // if (cookies.redditUser === undefined) {
+      //   redditCookie(setCookies);
+      // }
+      // Redirect to loading page
+      console.log('Remember me is set to true');
+      setremeberMe(true);
+    } else {
+      // No Cookie by Back End
+      console.log('Remember me is set to false');
+      setremeberMe(false);
+    }
+  }, []);
+
+  const caption = (
+    <>
+      Tell us the username and email address associated with
+      your Reddit account, and weโ€™ll send you an email with a link to reset your password.
+    </>
+  );
+
+  return (
+    <AuthenticationBody mnwidth="280px" mxwidth="440px" data-testid="forgetpassword-test">
+      {remeberMe ? <LoadingPage /> : (
+        <>
+          <AuthenticationHeader reddit title="Reset your password" caption={caption} fontSize="14px" />
+          <FirstPartyContainer
+            noValidate
+            onSubmit={(e) => {
+              e.preventDefault(); recoverPassword(
+                setLoading,
+                email,
+                setEmail,
+                userName,
+                setUserName,
+                setDisabled,
+                setbuttonText,
+                setRedirectCaption,
+              );
+            }}
+          >
+            <RedditTextField
+              label="Username"
+              variant="filled"
+              type="text"
+              required
+              InputProps={{
+                endAdornment: (
+                  userName.icon
+                ),
+                disableUnderline: true,
+              }}
+              clr={userName.color}
+              onChange={(e) => {
+                setUserName((prevState) => ({
+                  ...prevState,
+                  input: e.target.value.trim(),
+                }));
+                checkUserName(e.target.value.trim(), userName.error, setUserName);
+              }}
+              helperText={userName.error}
+              data-testid="forgetpassword-username-input"
+            />
+
+            <RedditTextField
+              label="Email Address"
+              variant="filled"
+              required
+              InputProps={{
+                endAdornment: (
+                  email.icon
+                ),
+                disableUnderline: true,
+              }}
+              clr={email.color}
+              onChange={(e) => {
+                setEmail((prevState) => ({
+                  ...prevState,
+                  input: e.target.value.trim(),
+                }));
+                checkEmail(e.target.value.trim(), setEmail);
+              }}
+              helperText={email.error}
+              data-testid="forgetpassword-email-input"
+            />
+            <RedditLoadingButton type="submit" width="155px" loading={loading} disabled={disabled} data-testid="reset-password-btn-test">
+              {buttonText}
+            </RedditLoadingButton>
+            {redirectCaption
+              ? (
+                <Typography color="primary" fontSize="12px" fontFamily={fonts['system-ui']} fontWeight="600" margin="20px 0px" data-testid="forgetpassword-redirect-caption-test">
+                  Thanks! If your Reddit username and email address match, youโ€™ll get an email with a link to reset your password shortly.
+                </Typography>
+              )
+              : null}
+            <StyledLink href="/username" fontWeight="600" capital="uppercase">FORGOT USERNAME?</StyledLink>
+          </FirstPartyContainer>
+          <Typography paragraph fontSize="12px" margin="10px 0px">
+            Donโ€™t have an email or need assistance logging in? GET HELP
+          </Typography>
+
+          <Typography paragraph fontSize="12px" marginTop="10px" color="#3394DC">
+            <StyledLink href="/login" fontWeight="600" capital="uppercase">log in</StyledLink>
+            {' โ€ข '}
+            <StyledLink href="/register" fontWeight="600" capital="uppercase">sign up</StyledLink>
+          </Typography>
+        </>
+      )}
+    </AuthenticationBody>
+  );
+}
+
+export default ForgetPassword;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_ForgetPassword_ForgetPasswordServer.js.html b/docs/components_Authentication_ForgetPassword_ForgetPasswordServer.js.html new file mode 100644 index 00000000..779a8efa --- /dev/null +++ b/docs/components_Authentication_ForgetPassword_ForgetPasswordServer.js.html @@ -0,0 +1,171 @@ + + + + + JSDoc: Source: components/Authentication/ForgetPassword/ForgetPasswordServer.js + + + + + + + + + + +
+ +

Source: components/Authentication/ForgetPassword/ForgetPasswordServer.js

+ + + + + + +
+
+
// mui components
+import DoneIcon from '@mui/icons-material/Done';
+
+// services
+import axios from '../../../services/instance';
+
+// styles
+import { wrongIcon, rightIcon } from '../styles';
+import theme from '../../../styles/theme';
+
+// scripts
+
+import { checkEmail } from '../authenticationServer';
+
+/**
+ *
+ * @param {string} username --userName Object
+ * @param {string} error --error Message
+ * @param {setfunction}setUserName --setfunction for the userName
+ * @returns {void}
+ */
+export const checkUserName = (username, error, setUserName) => {
+  // console.log(username); //must be passed expilicity
+  // console.log('Check User');
+  // console.log(error); //must be passed expilicity
+  if (error === "That user doesn't exist") {
+    // wait for Data Base
+    return;
+  }
+  // Check Username bwteen 3-20 characters
+  if (username.length < 3 || username.length > 20) {
+    // console.log('length problem');
+    setUserName((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'Username must be between 3 and 20 characters',
+    }));
+    return;
+  }
+  // else Valid
+  setUserName((prevState) => ({
+    ...prevState,
+    color: theme.palette.primary.main,
+    icon: rightIcon,
+    error: null,
+  }));
+};
+
+/**
+ *
+ * Recover Email
+ * @param {setfunction} setLoading
+ * @param {object} email --email object to recoverPassword with
+ * @param {object} userName --userName object to recoverPassword with
+ * @param {setFunction} setUserName --setfunction for the userName
+ * @param {setFunction} setDisabled --setfunction for the setting Button Disabled or Enabled
+ * @param {setFunction} setbuttonText --setfunction for the Button Text
+ * @param {setFunction} setRedirectCaption --setfunction for the Caption in SignUp Page
+ * @returns {void}
+ */
+export const recoverPassword = (
+  setLoading,
+  email,
+  setEmail,
+  userName,
+  setUserName,
+  setDisabled,
+  setbuttonText,
+  setRedirectCaption,
+) => {
+  // console.log(userName); //correct
+  setLoading(true);
+  // Setting error in case of first time
+  checkEmail(email.input, setEmail);
+  checkUserName(userName.input, userName.error, setUserName);
+
+  // Case he didn't enter anything
+  if (email.input === '' || userName.input === '') {
+    setLoading(false);
+    return;
+  }
+
+  // There are some errors in the email or username
+  if (userName.error !== "That user doesn't exist" && (email.error != null || userName.error != null)) {
+    setLoading(false);
+    return;
+  }
+
+  axios.post('/users/forgot_password', { email: email.input, userName: userName.input }).then((response) => {
+    if (response.status === 204 || response.status === 201 || response.status === 200) {
+      setUserName((prevState) => ({
+        ...prevState,
+        color: theme.palette.primary.main,
+        icon: rightIcon,
+        error: null,
+      }));
+      setTimeout(() => {
+        setLoading(false);
+        setDisabled(true);
+        setbuttonText(<DoneIcon />);
+        setRedirectCaption(true);
+      }, 1000);
+    }
+  }).catch((error) => {
+    setLoading(false);
+    console.log(error);
+    if (error.response?.status === 404) {
+      // This user Doesn't exist
+      setUserName((prevState) => ({
+        ...prevState,
+        color: theme.palette.error.main,
+        icon: wrongIcon,
+        error: 'That user doesn\'t exist',
+      }));
+      console.log(error.response?.errorMessage);
+    }
+    // 400 provode username and Password[Isn't reached]
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_ForgetUsername_ForgetUsername.jsx.html b/docs/components_Authentication_ForgetUsername_ForgetUsername.jsx.html new file mode 100644 index 00000000..5f192ef3 --- /dev/null +++ b/docs/components_Authentication_ForgetUsername_ForgetUsername.jsx.html @@ -0,0 +1,169 @@ + + + + + JSDoc: Source: components/Authentication/ForgetUsername/ForgetUsername.jsx + + + + + + + + + + +
+ +

Source: components/Authentication/ForgetUsername/ForgetUsername.jsx

+ + + + + + +
+
+
import { useEffect, useState } from 'react';
+import { useCookies } from 'react-cookie';
+
+// mui components
+import { Typography } from '@mui/material';
+
+// componenents
+import AuthenticationHeader from '../AuthenticationHeader/AuthenticationHeader';
+import LoadingPage from '../LoadingPage/LoadingPage';
+import Email from '../Email/Email';
+
+// styles
+import { AuthenticationBody, StyledLink } from '../styles';
+import theme, { fonts } from '../../../styles/theme';
+
+// server
+
+import { recoverUsername } from './forgetUsernameServer';
+
+// scripts
+import { redditCookie } from '../authenticationServer';
+
+// environment variables
+// const { REACT_APP_ENV } = process.env;
+
+/**
+ * Component for Forget Username Page
+ *
+ * @component
+ * @returns {React.Component} --Forget Username page
+ */
+
+function ForgetUsername() {
+  // states
+  const [email, setEmail] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+  const [remeberMe, setremeberMe] = useState(false);
+  const [loading, setLoading] = useState(false);
+  const [verified, setVerified] = useState(false);
+  const [buttonText, setbuttonText] = useState('Email Me');
+  const [disabled, setDisabled] = useState(false);
+  const [redirectCaption, setRedirectCaption] = useState(false);
+
+  // cookies
+  const [cookies, setCookies, removeCookie] = useCookies(['redditUser']);
+
+  // useEffect
+  useEffect(() => {
+    // Check on Cookies
+    // developememt
+    /// Ask if this user already loggied in the back
+    redditCookie(setCookies, removeCookie);
+    // if logged in in the back end
+    if (cookies.redditUser !== undefined) {
+      // production
+      // Update Cookie
+      // redditCookie(setCookies);
+      // check on Reddit cookie
+      // if (cookies.redditUser === undefined) {
+      //   redditCookie(setCookies);
+      // }
+      // Redirect to loading page
+      console.log('Remember me is set to true');
+      setremeberMe(true);
+    } else {
+      // No Cookie by Back End
+      console.log('Remember me is set to false');
+      setremeberMe(false);
+    }
+  }, []);
+
+  const caption = (
+    <>
+      Tell us the email address associated with your Reddit account, and weโ€™ll
+      send you an email with your username.
+    </>
+  );
+
+  return (
+    <AuthenticationBody mnwidth="280px" mxwidth="440px" data-testid="forgetusername-test">
+      {remeberMe ? <LoadingPage /> : (
+        <>
+          <AuthenticationHeader reddit title="Recover your username" caption={caption} fontSize="14px" />
+          <Email
+            email={email}
+            setEmail={setEmail}
+            onSubmitFn={() => recoverUsername(setLoading, email, verified, setDisabled, setbuttonText, setRedirectCaption)}
+            loading={loading}
+            buttonText={buttonText}
+            btnWidth="155px"
+            fieldText="Email Address"
+            recaptcha
+            setVerified={setVerified}
+            disabled={disabled}
+          />
+
+          {redirectCaption
+            ? <Typography color="primary" fontSize="12px" fontFamily={fonts['system-ui']} fontWeight="600" margin="20px 0px" data-testid="forgetusername-redirect-caption-test">Thanks! If there are any Reddit accounts associated with that email address, youโ€™ll get an email with your usernames(s) shortly</Typography>
+            : null}
+          <Typography paragraph fontSize="12px" margin="0px 0px 10px 0px">
+            Don
+            {'\''}
+            t have an email or need assistance logging in? GET HELP
+          </Typography>
+
+          <Typography paragraph fontSize="12px" marginTop="10px" color="#3394DC">
+            <StyledLink href="/login" fontWeight="600" capital="uppercase">log in</StyledLink>
+            {' โ€ข '}
+            <StyledLink href="/register" fontWeight="600" capital="uppercase">sign up</StyledLink>
+          </Typography>
+        </>
+      )}
+    </AuthenticationBody>
+  );
+}
+
+export default ForgetUsername;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_ForgetUsername_forgetUsernameServer.js.html b/docs/components_Authentication_ForgetUsername_forgetUsernameServer.js.html new file mode 100644 index 00000000..b042497f --- /dev/null +++ b/docs/components_Authentication_ForgetUsername_forgetUsernameServer.js.html @@ -0,0 +1,115 @@ + + + + + JSDoc: Source: components/Authentication/ForgetUsername/forgetUsernameServer.js + + + + + + + + + + +
+ +

Source: components/Authentication/ForgetUsername/forgetUsernameServer.js

+ + + + + + +
+
+
// mui components
+import DoneIcon from '@mui/icons-material/Done';
+
+// services
+import axios from '../../../services/instance';
+
+/**
+ *
+ * recover Username
+ * @returns {void}
+ */
+export const recoverUsername = (
+  setLoading,
+  email,
+  verified,
+  setDisabled,
+  setbuttonText,
+  setRedirectCaption,
+) => {
+  // console.log(email);
+  setLoading(true);
+
+  // if there is a problem with email
+  if (email.error != null) {
+    setTimeout(() => {
+      setLoading(false);
+    }, 500);
+    return;
+  }
+
+  // not verified
+  if (!verified) {
+    setLoading(false);
+    return;
+  }
+
+  console.log('Calling');
+  // Accepted Call API
+  axios.post('/users/forgot_username', { email: email.input }).then((response) => {
+    console.log(response);
+    if (response.status === 204 || response.status === 201 || response.status === 200) {
+      setTimeout(() => {
+        setLoading(false);
+        setDisabled(true);
+        setbuttonText(<DoneIcon />);
+        setRedirectCaption(true);
+      }, 1000);
+    }
+  }).catch((error) => {
+    setLoading(false);
+    console.log(error);
+    if (error.response?.status === 404) {
+      // email not found in DB [Don't Give the user This info]
+      setTimeout(() => {
+        setLoading(false);
+        setDisabled(true);
+        setbuttonText(<DoneIcon />);
+        setRedirectCaption(true);
+      }, 1000);
+    } else {
+      // 400 empty username or password[Won't reach this case]
+    }
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_ForgetUsername_server.js.html b/docs/components_Authentication_ForgetUsername_server.js.html new file mode 100644 index 00000000..e30fa392 --- /dev/null +++ b/docs/components_Authentication_ForgetUsername_server.js.html @@ -0,0 +1,114 @@ + + + + + JSDoc: Source: components/Authentication/ForgetUsername/server.js + + + + + + + + + + +
+ +

Source: components/Authentication/ForgetUsername/server.js

+ + + + + + +
+
+
// mui components
+import DoneIcon from '@mui/icons-material/Done';
+
+// services
+import axios from '../../../services/instance';
+
+/**
+ *
+ * recover Username
+ * @returns {void}
+ */
+export const recoverUsername = (
+  setLoading,
+  email,
+  verified,
+  setDisabled,
+  setbuttonText,
+  setRedirectCaption,
+) => {
+  // console.log(email);
+  setLoading(true);
+
+  // if there is a problem with email
+  if (email.error != null) {
+    setTimeout(() => {
+      setLoading(false);
+    }, 500);
+    return;
+  }
+
+  // not verified
+  if (!verified) {
+    setLoading(false);
+    return;
+  }
+
+  // Accepted Call API
+  axios.post('/users/forgot_username', { email: email.input }).then((response) => {
+    // console.log(response);
+    if (response.status === 204 || response.status === 201 || response.status === 200) {
+      setTimeout(() => {
+        setLoading(false);
+        setDisabled(true);
+        setbuttonText(<DoneIcon />);
+        setRedirectCaption(true);
+      }, 1000);
+    }
+  }).catch((error) => {
+    setLoading(false);
+    console.log(error);
+    if (error.response?.status === 404) {
+      // email not found in DB [Don't Give the user This info]
+      setTimeout(() => {
+        setLoading(false);
+        setDisabled(true);
+        setbuttonText(<DoneIcon />);
+        setRedirectCaption(true);
+      }, 1000);
+    } else {
+      // 400 empty username or password[Won't reach this case]
+    }
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_LoadingPage_LoadingPage.jsx.html b/docs/components_Authentication_LoadingPage_LoadingPage.jsx.html new file mode 100644 index 00000000..a33305ab --- /dev/null +++ b/docs/components_Authentication_LoadingPage_LoadingPage.jsx.html @@ -0,0 +1,94 @@ + + + + + JSDoc: Source: components/Authentication/LoadingPage/LoadingPage.jsx + + + + + + + + + + +
+ +

Source: components/Authentication/LoadingPage/LoadingPage.jsx

+ + + + + + +
+
+
import { useEffect } from 'react';
+
+// mui components
+import { Typography } from '@mui/material';
+
+// componenets
+import AuthenticationHeader from '../AuthenticationHeader/AuthenticationHeader';
+
+// scripts
+import { redirectHome } from '../../../utils/Redirect';
+
+// styles
+import { StyledLink } from '../styles';
+
+/**
+ * Loading Page Component
+ * @returns {React.Component} - Main Body of Loading Page
+ */
+function LoadingPage() {
+  // effect
+  useEffect(() => {
+    redirectHome(1000);
+  }, []);
+
+  const caption = (
+    <>
+      <Typography paragraph fontSize={15}>
+        You are already logged in and will be redirected back to Reddit shortly.
+      </Typography>
+      <Typography paragraph fontSize={15}>
+        If you are not redirected automatically, follow
+        {' '}
+        <StyledLink onClick={() => { redirectHome(200); }} href="#" fontWeight="400" fontSize={14}>this link</StyledLink>
+        .
+      </Typography>
+    </>
+  );
+  return (
+    <AuthenticationHeader reddit title="Welcome back!" caption={caption} fontSize="14px" />
+  );
+}
+
+export default LoadingPage;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_LogIn_LogIn.jsx.html b/docs/components_Authentication_LogIn_LogIn.jsx.html new file mode 100644 index 00000000..baaf118d --- /dev/null +++ b/docs/components_Authentication_LogIn_LogIn.jsx.html @@ -0,0 +1,151 @@ + + + + + JSDoc: Source: components/Authentication/LogIn/LogIn.jsx + + + + + + + + + + +
+ +

Source: components/Authentication/LogIn/LogIn.jsx

+ + + + + + +
+
+
/* eslint-disable no-unused-vars */
+import { useEffect, useState } from 'react';
+import { useCookies } from 'react-cookie';
+
+// mui components
+import { Typography } from '@mui/material';
+
+// componenets
+import LoadingPage from '../LoadingPage/LoadingPage';
+import AuthenticationHeader from '../AuthenticationHeader/AuthenticationHeader';
+import ThirdParty from '../ThirdParty/ThirdParty';
+import Divider from '../Divider/Divider';
+import FirstParty from '../FirstParty/FirstParty';
+
+// styles
+import { AuthenticationBody, StyledLink } from '../styles';
+
+// scripts
+import { redditCookie } from '../authenticationServer';
+
+// environment variables
+// const { REACT_APP_ENV } = process.env;
+
+/**
+ * Login Page Component
+ * @returns {React.Component} - Main Body of Login Page
+ */
+function LogIn() {
+  // state
+  const [remeberMe, setRemeberMe] = useState(false);
+
+  // cookies
+  const [cookies, setCookies, removeCookie] = useCookies(['redditUser']);
+
+  // useEffect
+  useEffect(() => {
+    // Check on Cookies
+    // developememt
+    /// Ask if this user already loggied in the back
+    redditCookie(setCookies, removeCookie);
+    // if logged in in the back end
+    if (cookies.redditUser !== undefined) {
+      // production
+      // Update Cookie
+      // redditCookie(setCookies);
+      // check on Reddit cookie
+      // if (cookies.redditUser === undefined) {
+      //   redditCookie(setCookies);
+      // }
+      // Redirect to loading page
+      console.log('Remember me is set to true');
+      setRemeberMe(true);
+    } else {
+      // No Cookie by Back End
+      console.log('Remember me is set to false');
+      setRemeberMe(false);
+    }
+  }, []);
+
+  const caption = (
+    <>
+      By continuing, you agree to our
+      {' '}
+      <StyledLink fontWeight="400" href="https://www.redditinc.com/policies/user-agreement" capital="none">User Agreement</StyledLink>
+      {' '}
+      and
+      {' '}
+      <StyledLink fontWeight="400" href="https://www.reddit.com/policies/privacy-policy" capital="none">Privacy Policy </StyledLink>
+      .
+    </>
+  );
+
+  return (
+    <AuthenticationBody mnwidth="290px" mxwidth={remeberMe ? '440px' : '290px'} data-testid="login-test">
+      {remeberMe ? <LoadingPage /> : (
+        <>
+          <AuthenticationHeader reddit={false} title="Log in" caption={caption} />
+          <ThirdParty />
+          <Divider />
+          <FirstParty />
+          <Typography paragraph fontSize="12px" fontFamily="ibm-plex-sans,sans-serif">
+            Forgot your
+            {' '}
+            <StyledLink href="/username" fontWeight="400" capital="none">username</StyledLink>
+            {' or '}
+            <StyledLink href="/password" fontWeight="400" capital="none">password</StyledLink>
+            {' ?'}
+          </Typography>
+          <Typography paragraph fontSize={12}>
+            New to Reddit?
+            {' '}
+            <StyledLink href="/register" fontWeight="600" capital="uppercase">sign up</StyledLink>
+          </Typography>
+        </>
+      )}
+    </AuthenticationBody>
+  );
+}
+
+export default LogIn;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_ResetPassword_ResetPassword.jsx.html b/docs/components_Authentication_ResetPassword_ResetPassword.jsx.html new file mode 100644 index 00000000..ff553a2a --- /dev/null +++ b/docs/components_Authentication_ResetPassword_ResetPassword.jsx.html @@ -0,0 +1,195 @@ + + + + + JSDoc: Source: components/Authentication/ResetPassword/ResetPassword.jsx + + + + + + + + + + +
+ +

Source: components/Authentication/ResetPassword/ResetPassword.jsx

+ + + + + + +
+
+
import { useState, useEffect } from 'react';
+import { useParams } from 'react-router-dom';
+import { useCookies } from 'react-cookie';
+
+// mui components
+import { Typography } from '@mui/material';
+// import { Checkbox } from '@mui/material';
+
+// components
+import AuthenticationHeader from '../AuthenticationHeader/AuthenticationHeader';
+
+// styles
+import { CheckBoxConatiner } from './styles';
+import theme, { fonts } from '../../../styles/theme';
+import {
+  AuthenticationBody, FirstPartyContainer, StyledLink, RedditTextField, RedditLoadingButton,
+} from '../styles';
+
+// server
+import { resetPassword, checkToken } from './resetPasswordserver';
+
+// scripts
+import { checkPassword, matchPassword } from '../authenticationServer';
+
+/**
+ * Component for Reset Password Page
+ *
+ * @component
+ * @returns {React.Component} --ResetPassword Page Component
+ */
+function ResetPassword() {
+  // states
+  const [password, setPassword] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+  const [repassword, setRePassword] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+  // const [Logout, setLogOut] = useState(false);
+  const [buttonText, setbuttonText] = useState('set Password');
+  const [loading, setLoading] = useState(false);
+  const [redirectCaption, setRedirectCaption] = useState(false);
+  const [expiredToken, setExpiredToken] = useState(false);
+
+  // useCookies
+  // eslint-disable-next-line no-unused-vars
+  const [cookies, setCookies] = useCookies(['redditUser']);
+
+  // useParams
+  const { token } = useParams();
+
+  const caption = (
+    <>
+      Choose a new password here, then log in to your account.
+    </>
+  );
+
+  // useEffect
+  useEffect(() => {
+    // check if valid
+    if (!checkToken(token)) {
+      // invalid Token Redirect to ForgetPassword
+      window.location.pathname = 'password';
+    }
+  }, []);
+
+  return (
+    <AuthenticationBody mnwidth="280px" mxwidth="440px" data-testid="resetpassword-test">
+      <AuthenticationHeader reddit title="Reset your password" caption={caption} fontSize="14px" />
+      {/* <h1>{token}</h1> */}
+      <FirstPartyContainer noValidate onSubmit={(e) => { e.preventDefault(); resetPassword(setLoading, password, setPassword, repassword, token, setbuttonText, setRedirectCaption, setCookies, setRePassword, setExpiredToken); }}>
+        <RedditTextField
+          label="New Password"
+          variant="filled"
+          required
+          value={password.input}
+          InputProps={{
+            endAdornment: (
+              password.icon
+            ),
+            disableUnderline: true,
+          }}
+          clr={password.color}
+          onChange={(e) => {
+            setPassword((prevState) => ({
+              ...prevState,
+              input: e.target.value.trim(),
+            }));
+            checkPassword(e.target.value.trim(), setPassword, undefined);
+            matchPassword(repassword, e.target.value.trim(), setRePassword);
+          }}
+          helperText={password.error}
+          data-testid="resetpassword-password-input"
+        />
+        <RedditTextField
+          label="Verify Password"
+          variant="filled"
+          required
+          value={repassword.input}
+          InputProps={{
+            endAdornment: (
+              repassword.icon
+            ),
+            disableUnderline: true,
+          }}
+          clr={repassword.color}
+          onChange={(e) => {
+            matchPassword(password, e.target.value.trim(), setRePassword);
+            setRePassword((prevState) => ({
+              ...prevState,
+              input: e.target.value.trim(),
+            }));
+          }}
+          helperText={repassword.error}
+          data-testid="resetpassword-repassword-input"
+        />
+        <CheckBoxConatiner>
+          {/* <Checkbox sx={{ padding: '0px 5px 0px 0px' }} onChange={(event) => setLogOut(event.target.checked)} /> */}
+          <Typography fontSize="12px" fontWeight="400">
+            Changing your password logs you out of all browsers on your device(s).
+            {/* {' '} */}
+            {/* Checking this box also logs you out of all apps you have authorized. */}
+          </Typography>
+        </CheckBoxConatiner>
+        <RedditLoadingButton type="submit" width="155px" loading={loading} data-testid="set-newpassword-btn-test">
+          {buttonText}
+        </RedditLoadingButton>
+        {redirectCaption
+          ? <Typography color="primary" fontSize="12px" fontFamily={fonts['system-ui']} fontWeight="600" margin="20px 0px">youโ€™ve successfully changed your password.You can now log in using your new password</Typography>
+          : null}
+        {expiredToken
+          ? <Typography color="error" fontSize="12px" fontFamily={fonts['system-ui']} fontWeight="600" margin="0px 0px">Token has expired</Typography>
+          : null}
+      </FirstPartyContainer>
+      <Typography paragraph fontSize="12px" marginTop="10px" color="#3394DC">
+        <StyledLink href="/login" fontWeight="600" capital="uppercase">log in</StyledLink>
+        {' โ€ข '}
+        <StyledLink href="/register" fontWeight="600" capital="uppercase">sign up</StyledLink>
+      </Typography>
+    </AuthenticationBody>
+  );
+}
+
+export default ResetPassword;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_ResetPassword_resetPasswordserver.js.html b/docs/components_Authentication_ResetPassword_resetPasswordserver.js.html new file mode 100644 index 00000000..40d4adea --- /dev/null +++ b/docs/components_Authentication_ResetPassword_resetPasswordserver.js.html @@ -0,0 +1,142 @@ + + + + + JSDoc: Source: components/Authentication/ResetPassword/resetPasswordserver.js + + + + + + + + + + +
+ +

Source: components/Authentication/ResetPassword/resetPasswordserver.js

+ + + + + + +
+
+
// services
+import DoneIcon from '@mui/icons-material/Done';
+import axios from '../../../services/instance';
+
+// styles
+import { wrongIcon } from '../styles';
+import theme from '../../../styles/theme';
+
+// scripts
+import { redirectLogin } from '../../../utils/Redirect';
+
+/**
+*
+* Function to check if length of provided string 3-20 accordingly change color and mesaages of username input field
+* @param {string} username  -username to check on
+* @returns void
+*/
+// eslint-disable-next-line no-unused-vars
+export const resetPassword = (setLoading, password, setPassword, repassword, token, setbuttonText, setRedirectCaption, setCookies, setRePassword, setExpiredToken) => {
+  setExpiredToken(false);
+  setLoading(true);
+  if (password.error !== 'Weak Password must contain Capital letter and numbers' && (password.error != null || repassword.error != null)) {
+    setLoading(false);
+    return;
+  }
+  // check if Empty (case he didn't make any change in the input field)
+  if (password.input === '' || repassword.input === '') {
+    setPassword((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'Password must be at least 8 characters long',
+    }));
+    setLoading(false);
+    return;
+  }
+  // Check API with BE
+  axios.post(`/users/reset_password/${token}`, {
+    // =>Logout paramter ??
+    password: password.input,
+    confirmPassword: repassword.input,
+  }).then((response) => {
+    console.log(response);
+    if (response.status === 200 || response.status === 201) {
+      setTimeout(() => {
+        setbuttonText(<DoneIcon />);
+        setRedirectCaption(true);
+        redirectLogin(1000);
+      }, 500);
+    }
+  }).catch((error) => {
+    if (error.response.status === 401) {
+      // expired token
+      setExpiredToken(true);
+    } else if (error.response.status === 400) {
+      if (error.response.data.errorType === 2) {
+        setPassword((prevState) => ({
+          ...prevState,
+          color: theme.palette.error.main,
+          icon: wrongIcon,
+          error: 'Weak Password must contain Capital letter and numbers',
+        }));
+      }
+      // Non matching passwords(1)
+      // not provide(0)
+      // matchPassword(password, repassword, setRePassword);
+    }
+    setLoading(false);
+    console.log(error);
+  });
+};
+
+/**
+ *
+ * @param {string} token
+ * @returns bool if valid is true else false
+ */
+export const checkToken = async (token) => {
+  let x = false;
+  // Check Token Endpoint
+  const response = await axios.get(`/users/check_reset_token/${token}`).catch((error) => {
+    // Invalid Token
+    console.log(error);
+  });
+
+  // console.log(response.status);
+  if (response.status === 204 || response.status === 200) {
+    x = true;
+  }
+  return x;
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_SignUp_SignUp.jsx.html b/docs/components_Authentication_SignUp_SignUp.jsx.html new file mode 100644 index 00000000..57cada26 --- /dev/null +++ b/docs/components_Authentication_SignUp_SignUp.jsx.html @@ -0,0 +1,135 @@ + + + + + JSDoc: Source: components/Authentication/SignUp/SignUp.jsx + + + + + + + + + + +
+ +

Source: components/Authentication/SignUp/SignUp.jsx

+ + + + + + +
+
+
import { useEffect, useState } from 'react';
+import { useCookies } from 'react-cookie';
+
+// components
+import SignUpEmail from './SignUpEmail/SignUpEmail';
+import SignUpUsername from './SignUpUsername/SignUpUsername';
+import LoadingPage from '../LoadingPage/LoadingPage';
+
+// styles
+import { AuthenticationConatiner, AuthenticationBG, AuthenticationBody } from '../styles';
+import theme from '../../../styles/theme';
+
+// scripts
+
+import { redditCookie } from '../authenticationServer';
+
+/**
+ * SignUp Page Main Componnet with 2 view one for the Email and the Other for the userName
+ *
+ * @component
+ * @returns {React.Component} SignUp Page
+ */
+function SignUp() {
+  // states
+  const [remeberMe, setremeberMe] = useState(false);
+  const [userNamePage, setUserNamePage] = useState(false);
+  const [email, setEmail] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+  const [userName, setUserName] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+  const [password, setPassword] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null, score: 0,
+  });
+
+  // cookies
+  const [cookies, setCookies, removeCookie] = useCookies(['redditUser']);
+
+  // useEffect
+  useEffect(() => {
+    // Check on Cookies
+    // developememt
+    /// Ask if this user already loggied in the back
+    redditCookie(setCookies, removeCookie);
+    // if logged in in the back end
+    if (cookies.redditUser !== undefined) {
+      // production
+      // Update Cookie
+      // redditCookie(setCookies);
+      // check on Reddit cookie
+      // if (cookies.redditUser === undefined) {
+      //   redditCookie(setCookies);
+      // }
+      // Redirect to loading page
+      console.log('Remember me is set to true');
+      setremeberMe(true);
+    } else {
+      // No Cookie by Back End
+      console.log('Remember me is set to false');
+      setremeberMe(false);
+    }
+  }, []);
+
+  const signUpView = userNamePage
+    ? <SignUpUsername setUserNamePage={setUserNamePage} email={email} userName={userName} setUserName={setUserName} password={password} setPassword={setPassword} setCookies={setCookies} removeCookie={removeCookie} />
+    : <SignUpEmail setUserNamePage={setUserNamePage} email={email} setEmail={setEmail} />;
+
+  return (
+    <AuthenticationConatiner data-testid="signup-test">
+      {remeberMe
+        ? (
+          <>
+            <AuthenticationBG />
+            <AuthenticationBody mnwidth="280px" mxwidth="280px" data-testid="signup-email-test">
+              <LoadingPage />
+            </AuthenticationBody>
+          </>
+        )
+        : signUpView}
+    </AuthenticationConatiner>
+  );
+}
+export default SignUp;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_SignUp_SignUpEmail_SignUpEmail.jsx.html b/docs/components_Authentication_SignUp_SignUpEmail_SignUpEmail.jsx.html new file mode 100644 index 00000000..85746ef5 --- /dev/null +++ b/docs/components_Authentication_SignUp_SignUpEmail_SignUpEmail.jsx.html @@ -0,0 +1,130 @@ + + + + + JSDoc: Source: components/Authentication/SignUp/SignUpEmail/SignUpEmail.jsx + + + + + + + + + + +
+ +

Source: components/Authentication/SignUp/SignUpEmail/SignUpEmail.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+
+// mui compoenets
+import { Typography } from '@mui/material';
+
+// components
+import AuthenticationHeader from '../../AuthenticationHeader/AuthenticationHeader';
+import ThirdParty from '../../ThirdParty/ThirdParty';
+import Divider from '../../Divider/Divider';
+import Email from '../../Email/Email';
+
+// styles
+import { AuthenticationBG, AuthenticationBody, StyledLink } from '../../styles';
+
+/**
+ * SignUp Username and Password Page View
+ *
+ * @component
+ * @property {function} --setUserNamePage setView to Email Page on Back Button Click
+ * @property {object} --email email taken from user to sign up with
+ * @property {function} --setEmail set email taken from user
+ * @returns {React.Component} Email SignUp Component
+ */
+function SignUpEmail({ setUserNamePage, email, setEmail }) {
+  // states
+  const [loading, setLoading] = useState(false);
+
+  const continueEmail = () => {
+    // console.log(email);// true value but case no change wrong value
+    setLoading(true);
+    // Has error (syntax error Email or empty Email)
+    if (email.error !== null) {
+      setLoading(false);
+      return;
+    }
+    // check if Empty (case he didn't make any change in the input field)
+    if (email.input === '') {
+      setLoading(false);
+      return;
+    }
+
+    // Email is Accepted
+    setTimeout(() => {
+      setLoading(false);
+      setUserNamePage(true);
+    }, 500);
+  };
+
+  const caption = (
+    <>
+      By continuing, you are setting up a Reddit account and agree to our
+      {' '}
+      <StyledLink fontWeight="400" href="https://www.redditinc.com/policies/user-agreement" capital="none">User Agreement</StyledLink>
+      {' '}
+      and
+      {' '}
+      <StyledLink fontWeight="400" href="https://www.reddit.com/policies/privacy-policy" capital="none">Privacy Policy </StyledLink>
+      .
+    </>
+  );
+
+  return (
+    <>
+      <AuthenticationBG />
+      <AuthenticationBody mnwidth="280px" mxwidth="280px" data-testid="signup-email-test">
+        <AuthenticationHeader reddit={false} title="Sign up" caption={caption} />
+        <ThirdParty />
+        <Divider />
+        <Email email={email} setEmail={setEmail} onSubmitFn={continueEmail} loading={loading} width="280px" buttonText="continue" fieldText="Email" recaptcha={false} setVerified={null} disabled={false} />
+        <Typography paragraph fontSize={12}>
+          Already a redditor?
+          {' '}
+          <StyledLink href="/login" fontWeight="600" capital="uppercase">log in</StyledLink>
+        </Typography>
+      </AuthenticationBody>
+    </>
+  );
+}
+export default SignUpEmail;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_SignUp_SignUpUsername_SignUpUsername.jsx.html b/docs/components_Authentication_SignUp_SignUpUsername_SignUpUsername.jsx.html new file mode 100644 index 00000000..dd58fb0a --- /dev/null +++ b/docs/components_Authentication_SignUp_SignUpUsername_SignUpUsername.jsx.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Source: components/Authentication/SignUp/SignUpUsername/SignUpUsername.jsx + + + + + + + + + + +
+ +

Source: components/Authentication/SignUp/SignUpUsername/SignUpUsername.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+
+// mui components
+import { IconButton, Typography } from '@mui/material';
+import UpdateIcon from '@mui/icons-material/Update';
+
+// Components
+import PasswordStrengthBar from 'react-password-strength-bar';
+import ReCAPTCHA from 'react-google-recaptcha';
+
+// styles
+import {
+  BackLink, Body, ChooseUsernameContainer, Footer, Header, SuggestionBox, SuggestLink, TopBox,
+} from './styles';
+import {
+  FirstPartyContainer, RedditTextField, rightIcon, RedditLoadingButton,
+} from '../../styles';
+
+// server
+
+import { checkUserNameSignUp, signUp, generateRandomUsernamesServer } from './signupUsernameServer';
+
+// scripts
+import { checkPassword } from '../../authenticationServer';
+
+import theme, { fonts } from '../../../../styles/theme';
+
+// env Variables
+const { REACT_APP_SITEKEY } = process.env;
+
+/**
+ * SignUp Username and Password Page View
+ *
+ * @component
+ * @property {SetFunction} --setUserNamePage setView to Email Page on Back Button Click
+ * @property {object} --email setView to Email Page on Back Button Click
+ * @property {object} --userName userName to SignUp with
+ * @property {function} --setUserName to set UserName
+ * @property {object} --password password to SignUp with
+ * @property {function} --setPassword to set password
+ * @returns {React.Component} UserName and Password Form
+ */
+function SignUpUsername({
+  setUserNamePage, email, userName, setUserName, password, setPassword, setCookies, removeCookie,
+}) {
+  // states
+  const [defaultUserNameValue, setdefaultUserNameValue] = useState(userName?.input);
+  const [defaultPasswordValue, setdefaultPasswordValue] = useState(password?.input);
+  const [verified, setVerified] = useState(false);
+  const [loading, setLoading] = useState(false);
+  const [buttonTxt, setButtonText] = useState('Sign up');
+  const [disabled, setDisabled] = useState(false);
+  const [redirectCaption, setRedirectCaption] = useState(false);
+  const [click, setClick] = useState(false);
+
+  // server generate Random Names
+  const generatedUsernames = generateRandomUsernamesServer(5, click);
+
+  const signUpFunction = () => {
+    checkUserNameSignUp(userName?.input, setUserName);
+    checkPassword(password?.input, setPassword, password);
+    signUp(email, userName, setUserName, password, setPassword, verified, setLoading, setButtonText, setDisabled, setRedirectCaption, setCookies, removeCookie);
+  };
+
+  return (
+    <ChooseUsernameContainer data-testid="signup-username-test">
+      <Header>
+        <Typography variant="h1" fontSize={18} fontWeight={700} fontFamily="ibm-plex-sans,sans-serif" marginBottom="10px">
+          Choose your username
+        </Typography>
+        <Typography fontSize={14}>
+          Your username is how other community members will see you. This name will be used to
+          {' '}
+          credit you for things you share on Reddit. What should we call you?
+        </Typography>
+      </Header>
+      <Body>
+        <FirstPartyContainer width="350px" mnwidth="200px">
+          <RedditTextField
+            label="Choose a username"
+            variant="filled"
+            required
+            InputProps={{
+              endAdornment: (
+                userName?.icon
+              ),
+              disableUnderline: true,
+            }}
+            clr={userName?.color}
+            onChange={(e) => {
+              setUserName((prevState) => ({
+                ...prevState,
+                input: e.target.value.trim(),
+              }));
+              checkUserNameSignUp(e.target.value.trim(), setUserName);
+              setdefaultUserNameValue(e.target.value.trim());
+            }}
+            value={defaultUserNameValue || ''}
+            data-testid="username-signup-field-test"
+            helperText={userName?.error}
+          />
+          <PasswordStrengthBar
+            password={password?.input}
+            minLength={4}
+            onChangeScore={(e) => (setPassword((prevState) => ({
+              ...prevState,
+              score: e,
+            })))}
+            scoreWords={[]}
+            shortScoreWord=""
+          />
+          <RedditTextField
+            label="password"
+            variant="filled"
+            type="password"
+            required
+            InputProps={{
+              endAdornment: (
+                password?.icon
+              ),
+              disableUnderline: true,
+            }}
+            clr={password?.color}
+            onChange={(e) => {
+              setPassword((prevState) => ({
+                ...prevState,
+                input: e.target.value.trim(),
+              }));
+              checkPassword(e.target.value.trim(), setPassword, undefined);
+              setdefaultPasswordValue(e.target.value.trim());
+            }}
+            value={defaultPasswordValue || ''}
+            helperText={password?.error}
+            data-testid="password-signup-field-test"
+          />
+          <ReCAPTCHA
+            sitekey={REACT_APP_SITEKEY}
+            onExpired={() => setVerified(false)}
+            onChange={() => setVerified(true)}
+            size="normal"
+            sx={{ width: '320px' }}
+          />
+        </FirstPartyContainer>
+        <SuggestionBox>
+          <TopBox>
+            <Typography variant="p" fontSize={14}>
+              Here are some username suggestions
+            </Typography>
+            <IconButton aria-label="delete" color="primary" onClick={() => setClick(!click)}>
+              <UpdateIcon />
+            </IconButton>
+          </TopBox>
+          {generatedUsernames ? (generatedUsernames.map((i) => (
+            <SuggestLink
+              key={i}
+              onClick={() => {
+                setUserName((prevState) => ({
+                  ...prevState,
+                  color: theme.palette.primary.main,
+                  icon: rightIcon,
+                  error: null,
+                  input: i,
+                }));
+                setdefaultUserNameValue(i);
+              }}
+              href="#"
+              helperText={password.error}
+              data-testid={`suggest-username-${i}-test`}
+            >
+              {i}
+            </SuggestLink>
+          ))) : null}
+        </SuggestionBox>
+      </Body>
+      {redirectCaption
+        ? <Typography color="primary" fontSize="12px" fontFamily={fonts['system-ui']} fontWeight="600" margin="auto">You are now logged in. You will soon be redirected</Typography>
+        : null}
+      <Footer>
+        <BackLink onClick={() => { if (disabled) return; setUserNamePage(false); }} href="#">Back</BackLink>
+        <RedditLoadingButton
+          width="155px"
+          onClick={signUpFunction}
+          loading={loading}
+          disabled={disabled}
+          data-testid="sigup-btn-test"
+        >
+          {buttonTxt}
+        </RedditLoadingButton>
+      </Footer>
+    </ChooseUsernameContainer>
+  );
+}
+export default SignUpUsername;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_SignUp_SignUpUsername_server.js.html b/docs/components_Authentication_SignUp_SignUpUsername_server.js.html new file mode 100644 index 00000000..54be9c92 --- /dev/null +++ b/docs/components_Authentication_SignUp_SignUpUsername_server.js.html @@ -0,0 +1,300 @@ + + + + + JSDoc: Source: components/Authentication/SignUp/SignUpUsername/server.js + + + + + + + + + + +
+ +

Source: components/Authentication/SignUp/SignUpUsername/server.js

+ + + + + + +
+
+
import { useEffect, useState } from 'react';
+import { generateUsername } from 'unique-username-generator';
+
+// mui components
+import DoneIcon from '@mui/icons-material/Done';
+
+// services
+import axios from '../../../../services/instance';
+
+// styles
+import { wrongIcon, rightIcon } from '../../styles';
+import theme from '../../../../styles/theme/index';
+
+// Scripts
+import { redditCookie } from '../../authenticationServer';
+import { redirectHome } from '../../../../utils/Redirect';
+
+// utils
+import replaceDashWithUnderScore from '../../../../utils/replaceDashWithUnderScore';
+/**
+ *
+ * check if username length [3-20], if valid username syntax,if username is unique and change state object accordingly
+ * @param {string} username  --username to check for
+ * @param {sstFunction} setUserName --setFunction for the userName State
+ * @returns {void}
+ */
+export const checkUserNameSignUp = (username, setUserName) => {
+  // console.log(username);// New value must be passsed
+  // Check Username bwteen 3-20 characters
+  if (username.length < 3 || username.length > 20) {
+    setUserName((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'Username must be between 3 and 20 characters',
+    }));
+    return;
+  }
+
+  // Check Invalid UserName
+  if (!/^[A-Za-z0-9_-]*$/.test(username)) {
+    // console.log('invalid');
+    setUserName((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'Letters, numbers, dashes, and underscores only. Please try again without symbols.',
+    }));
+    return;
+  }
+
+  // Check Unique Username
+  axios.get(`/users/username_available?userName=${username}`).then((response) => {
+    if (response.status === 200) {
+      if (response.data.available === true) {
+        // Unique
+        setUserName((prevState) => ({
+          ...prevState,
+          color: theme.palette.primary.main,
+          icon: rightIcon,
+          error: null,
+        }));
+      } else {
+        // Repeated
+        setUserName((prevState) => ({
+          ...prevState,
+          color: theme.palette.error.main,
+          icon: wrongIcon,
+          error: 'That username is already taken.',
+        }));
+      }
+    }
+  }).catch((error) => {
+    console.log(error);
+  });
+};
+
+/**
+ *
+ * SignUp new User Function  if there is no a problem with the fields and verification the API is called
+ * else not
+ * Check for the Password Strength
+ * Check if Verified to continue SignUp
+ * @param {object} email --email object to signup with
+ * @param {object} userName --userName object to signup with
+ * @param {object} password --password object to signup with
+ * @param {setFunction} setPassword --setfunction for the password
+ * @param {state} verified --bool if verified by the Captcha
+ * @param {setfunction} setLoading --setfunction for the Laoding state of the button
+ * @param {setfunction} setButtonText --setfunction for the Button Text
+ * @param {setfunction} setDisabled --setfunction for the setting Button Disabled or Enabled
+ * @param {setfunction} setRedirectCaption --setfunction for the Caption in SignUp Page
+ * @returns {void}
+ */
+export const signUp = (
+  email,
+  userName,
+  setuserName,
+  password,
+  setPassword,
+  verified,
+  setLoading,
+  setButtonText,
+  setDisabled,
+  setRedirectCaption,
+  setCookies,
+  removeCookie,
+  popUp = false,
+  handleClose = null,
+) => {
+  // console.log(email);
+  // console.log(userName);// true value but case no change wrong value
+  // console.log(password);// true value but case no change wrong value
+  setLoading(true);
+
+  // check if there is any errors
+  if (userName.error != null || password.error != null) {
+    setLoading(false);
+    return;
+  }
+
+  // check if Empty (case he didn't make any change in the input field)
+  if (userName.input === '' || password.input === '') {
+    setLoading(false);
+    return;
+  }
+
+  // Weak Password
+  if (password.score < 2) {
+    setPassword((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'This Password isn\'t acceptable',
+    }));
+    setLoading(false);
+    return;
+  }
+
+  // check if verified
+  if (!verified) {
+    setLoading(false);
+    return;
+  }
+  // SignUpEndPoint
+  axios.post('/users/signup', {
+    // console.log(userName.input, password.input, email.input);
+    userName: userName.input,
+    email: email.input,
+    password: password.input,
+  }).then((response) => {
+    setLoading(false);
+    if (response.status === 201 || response.status === 200) {
+      setButtonText(<DoneIcon />);
+      setDisabled(true);
+      setRedirectCaption(true);
+      // Add Reddit Cookie
+
+      if (popUp === false) { redirectHome(1000); redditCookie(setCookies, removeCookie); } else {
+        // PopUp window
+        setTimeout(() => {
+          redditCookie(setCookies, removeCookie);
+          handleClose();
+        }, 1000);
+      }
+    } else {
+      console.log('Error');
+    }
+  }).catch((error) => {
+    if (error.response.data.errorType === 1) {
+      setLoading(false);
+      // weak password
+      setPassword((prevState) => ({
+        ...prevState,
+        color: theme.palette.error.main,
+        icon: wrongIcon,
+        error: 'This Password isn\'t acceptable',
+      }));
+    } else if (error.response.data.errorType === 2) {
+      setLoading(false);
+      // repeated mail or username but for our logic it is only email
+      // Repeated
+      setuserName((prevState) => ({
+        ...prevState,
+        color: theme.palette.error.main,
+        icon: wrongIcon,
+        error: 'That user already exists.',
+      }));
+    }
+    console.log(error);
+  });
+};
+
+/**
+ * This function works as a server for generating random usernames
+ *
+ * @function generateRandomUsernamesServer
+ * @param {number} numberOfGeneratedUsernames - the maximum number of random usernames to be generated
+ * @param {React.State} deps - the dependencies on which random usernames generated
+ * @returns {Array.<string>} generated usernames
+ */
+export const generateRandomUsernamesServer = (numberOfGeneratedUsernames, deps) => {
+  const [generatedUsernames, setGeneratedUsernames] = useState(null);
+  useEffect(() => {
+    (async () => {
+      let counter = 0;
+      const temp = [];
+      do {
+        let error = '';
+        let newUserName;
+        do {
+          newUserName = generateUsername();
+          newUserName = newUserName.slice(0, 20);
+        }
+        while (newUserName.length < 3);
+        const username = replaceDashWithUnderScore(newUserName);
+        const response = await axios.get('/users/username_available', {
+          params: {
+            userName: username,
+          },
+        }).catch((e) => {
+          error = e;
+        });
+        const { data, status: statusCode } = response;
+        if (error) {
+          setGeneratedUsernames(['something went wrong']);
+          return;
+        }
+
+        if (statusCode === 400) {
+          const { message } = data;
+          setGeneratedUsernames([message]);
+          return;
+        }
+
+        if (data.available === true) {
+          // unique
+          counter += 1;
+          temp.push(username);
+        }
+      } while (counter < numberOfGeneratedUsernames);
+      // console.log(temp);
+      setGeneratedUsernames(temp);
+    })();
+  }, [deps]);
+  return generatedUsernames;
+};
+
+export default generateRandomUsernamesServer;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_SignUp_SignUpUsername_signupUsernameServer.js.html b/docs/components_Authentication_SignUp_SignUpUsername_signupUsernameServer.js.html new file mode 100644 index 00000000..6e386b57 --- /dev/null +++ b/docs/components_Authentication_SignUp_SignUpUsername_signupUsernameServer.js.html @@ -0,0 +1,303 @@ + + + + + JSDoc: Source: components/Authentication/SignUp/SignUpUsername/signupUsernameServer.js + + + + + + + + + + +
+ +

Source: components/Authentication/SignUp/SignUpUsername/signupUsernameServer.js

+ + + + + + +
+
+
import { useEffect, useState } from 'react';
+import { generateUsername } from 'unique-username-generator';
+
+// mui components
+import DoneIcon from '@mui/icons-material/Done';
+
+// services
+import axios from '../../../../services/instance';
+
+// styles
+import { wrongIcon, rightIcon } from '../../styles';
+import theme from '../../../../styles/theme/index';
+
+// Scripts
+import { redditCookie } from '../../authenticationServer';
+import { redirectHome } from '../../../../utils/Redirect';
+
+// utils
+import replaceDashWithUnderScore from '../../../../utils/replaceDashWithUnderScore';
+/**
+ *
+ * check if username length [3-20], if valid username syntax,if username is unique and change state object accordingly
+ * @param {string} username  --username to check for
+ * @param {sstFunction} setUserName --setFunction for the userName State
+ * @returns {void}
+ */
+export const checkUserNameSignUp = (username, setUserName) => {
+  // console.log(username);// New value must be passsed
+  // Check Username bwteen 3-20 characters
+  if (username.length < 3 || username.length > 20) {
+    setUserName((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'Username must be between 3 and 20 characters',
+    }));
+    return;
+  }
+
+  // Check Invalid UserName
+  if (!/^[A-Za-z0-9_-]*$/.test(username)) {
+    // console.log('invalid');
+    setUserName((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'Letters, numbers, dashes, and underscores only. Please try again without symbols.',
+    }));
+    return;
+  }
+
+  // Check Unique Username
+  axios.get(`/users/username_available?userName=${username}`).then((response) => {
+    if (response.status === 200) {
+      if (response.data.available === true) {
+        // Unique
+        setUserName((prevState) => ({
+          ...prevState,
+          color: theme.palette.primary.main,
+          icon: rightIcon,
+          error: null,
+        }));
+      } else {
+        // Repeated
+        setUserName((prevState) => ({
+          ...prevState,
+          color: theme.palette.error.main,
+          icon: wrongIcon,
+          error: 'That username is already taken.',
+        }));
+      }
+    }
+  }).catch((error) => {
+    console.log(error);
+  });
+};
+
+/**
+ *
+ * SignUp new User Function  if there is no a problem with the fields and verification the API is called
+ * else not
+ * Check for the Password Strength
+ * Check if Verified to continue SignUp
+ * @param {object} email --email object to signup with
+ * @param {object} userName --userName object to signup with
+ * @param {object} password --password object to signup with
+ * @param {setFunction} setPassword --setfunction for the password
+ * @param {state} verified --bool if verified by the Captcha
+ * @param {setfunction} setLoading --setfunction for the Laoding state of the button
+ * @param {setfunction} setButtonText --setfunction for the Button Text
+ * @param {setfunction} setDisabled --setfunction for the setting Button Disabled or Enabled
+ * @param {setfunction} setRedirectCaption --setfunction for the Caption in SignUp Page
+ * @returns {void}
+ */
+export const signUp = (
+  email,
+  userName,
+  setuserName,
+  password,
+  setPassword,
+  verified,
+  setLoading,
+  setButtonText,
+  setDisabled,
+  setRedirectCaption,
+  setCookies,
+  removeCookie,
+  popUp = false,
+  handleClose = null,
+) => {
+  // console.log(email);
+  // console.log(userName);// true value but case no change wrong value
+  // console.log(password);// true value but case no change wrong value
+  setLoading(true);
+
+  // check if there is any errors
+  if (userName.error != null || password.error != null) {
+    setLoading(false);
+    return;
+  }
+
+  // check if Empty (case he didn't make any change in the input field)
+  if (userName.input === '' || password.input === '') {
+    setLoading(false);
+    return;
+  }
+
+  // Weak Password
+  if (password.score < 2) {
+    setPassword((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'This Password isn\'t acceptable',
+    }));
+    setLoading(false);
+    return;
+  }
+
+  // check if verified
+  if (!verified) {
+    setLoading(false);
+    return;
+  }
+  // SignUpEndPoint
+  axios.post('/users/signup', {
+    // console.log(userName.input, password.input, email.input);
+    userName: userName.input,
+    email: email.input,
+    password: password.input,
+  }).then((response) => {
+    setLoading(false);
+    if (response.status === 201 || response.status === 200) {
+      setButtonText(<DoneIcon />);
+      setDisabled(true);
+      setRedirectCaption(true);
+      // Add Reddit Cookie
+
+      if (popUp === false) {
+        redirectHome(1000);
+        redditCookie(setCookies, removeCookie);
+      } else {
+        // PopUp window
+        setTimeout(() => {
+          redditCookie(setCookies, removeCookie);
+          handleClose();
+        }, 1000);
+      }
+    } else {
+      console.log('Error');
+    }
+  }).catch((error) => {
+    if (error.response.data.errorType === 1) {
+      setLoading(false);
+      // weak password
+      setPassword((prevState) => ({
+        ...prevState,
+        color: theme.palette.error.main,
+        icon: wrongIcon,
+        error: 'This Password isn\'t acceptable',
+      }));
+    } else if (error.response.data.errorType === 2) {
+      setLoading(false);
+      // repeated mail or username but for our logic it is only email
+      // Repeated
+      setuserName((prevState) => ({
+        ...prevState,
+        color: theme.palette.error.main,
+        icon: wrongIcon,
+        error: 'That user already exists.',
+      }));
+    }
+    console.log(error);
+  });
+};
+
+/**
+ * This function works as a server for generating random usernames
+ *
+ * @function generateRandomUsernamesServer
+ * @param {number} numberOfGeneratedUsernames - the maximum number of random usernames to be generated
+ * @param {React.State} deps - the dependencies on which random usernames generated
+ * @returns {Array.<string>} generated usernames
+ */
+export const generateRandomUsernamesServer = (numberOfGeneratedUsernames, deps) => {
+  const [generatedUsernames, setGeneratedUsernames] = useState(null);
+  useEffect(() => {
+    (async () => {
+      let counter = 0;
+      const temp = [];
+      do {
+        let error = '';
+        let newUserName;
+        do {
+          newUserName = generateUsername();
+          newUserName = newUserName.slice(0, 20);
+        }
+        while (newUserName.length < 3);
+        const username = replaceDashWithUnderScore(newUserName);
+        const response = await axios.get('/users/username_available', {
+          params: {
+            userName: username,
+          },
+        }).catch((e) => {
+          error = e;
+        });
+        const { data, status: statusCode } = response;
+        if (error) {
+          setGeneratedUsernames(['something went wrong']);
+          return;
+        }
+
+        if (statusCode === 400) {
+          const { message } = data;
+          setGeneratedUsernames([message]);
+          return;
+        }
+
+        if (data.available === true) {
+          // unique
+          counter += 1;
+          temp.push(username);
+        }
+      } while (counter < numberOfGeneratedUsernames);
+      // console.log(temp);
+      setGeneratedUsernames(temp);
+    })();
+  }, [deps]);
+  return generatedUsernames;
+};
+
+export default generateRandomUsernamesServer;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_ThirdParty_ThirdParty.jsx.html b/docs/components_Authentication_ThirdParty_ThirdParty.jsx.html new file mode 100644 index 00000000..510697df --- /dev/null +++ b/docs/components_Authentication_ThirdParty_ThirdParty.jsx.html @@ -0,0 +1,121 @@ + + + + + JSDoc: Source: components/Authentication/ThirdParty/ThirdParty.jsx + + + + + + + + + + +
+ +

Source: components/Authentication/ThirdParty/ThirdParty.jsx

+ + + + + + +
+
+
import { useCookies } from 'react-cookie';
+
+// Google and Facebook Service components
+import { gapi } from 'gapi-script';
+import GoogleLogin from 'react-google-login';
+import FacebookLogin from 'react-facebook-login/dist/facebook-login-render-props';
+
+// server
+import {
+  responseGoogleSuccess, responseGoogleFail, responseFacebook,
+
+} from './thirdpartyServer';
+
+// styles
+import { ThirdPartyContainer } from './styles';
+import ThirdPartyButton from './ThirdPartyButton/ThirdPartyButton';
+
+import Google from '../../../assets/images/google.png';
+import Facebook from '../../../assets/images/facebook.png';
+
+// environment variables
+const { REACT_APP_GOOGLECLIENTID, REACT_APP_FACEBOOKCLIENTID } = process.env;
+
+/**
+ * Third Party [Google and Facebook] Components
+ *  @component
+ * @returns {React.Component} - Continue with google and Facebook
+ */
+function ThirdParty() {
+  // cookies
+  // eslint-disable-next-line no-unused-vars
+  const [cookies, setCookies] = useCookies(['redditUser']);
+
+  // Google Auth Service
+  const googleClientId = REACT_APP_GOOGLECLIENTID;
+  const initClient = () => {
+    gapi.auth2.init({
+      clientId: googleClientId,
+      scope: '',
+    });
+  };
+  gapi.load('client:auth2', initClient);
+
+  // Facebook Auth Service
+  const facebookAppId = REACT_APP_FACEBOOKCLIENTID;
+
+  return (
+    <ThirdPartyContainer>
+      <GoogleLogin
+        clientId={googleClientId}
+        render={(renderProps) => (
+          <ThirdPartyButton onClick={renderProps.onClick} img={Google} alt="Google" txt="continue with google" />
+        )}
+        onSuccess={(googleResponse) => responseGoogleSuccess(googleResponse, setCookies)}
+        onFailure={responseGoogleFail}
+        cookiePolicy="single_host_origin"
+        testid="google-btn-test"
+      />
+      <FacebookLogin
+        appId={facebookAppId}
+        callback={(facebookResponse) => responseFacebook(facebookResponse, setCookies)}
+        render={(renderProps) => (
+          <ThirdPartyButton onClick={renderProps.onClick} img={Facebook} alt="Facebook" txt="continue with facebook" />
+        )}
+      />
+    </ThirdPartyContainer>
+  );
+}
+
+export default ThirdParty;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_ThirdParty_ThirdPartyButton_ThirdPartyButton.jsx.html b/docs/components_Authentication_ThirdParty_ThirdPartyButton_ThirdPartyButton.jsx.html new file mode 100644 index 00000000..c114d705 --- /dev/null +++ b/docs/components_Authentication_ThirdParty_ThirdPartyButton_ThirdPartyButton.jsx.html @@ -0,0 +1,70 @@ + + + + + JSDoc: Source: components/Authentication/ThirdParty/ThirdPartyButton/ThirdPartyButton.jsx + + + + + + + + + + +
+ +

Source: components/Authentication/ThirdParty/ThirdPartyButton/ThirdPartyButton.jsx

+ + + + + + +
+
+
import { ThirdPartyBtn, ButtonIcon } from './styles';
+
+/**
+ * Third Party Button
+ *  @component
+ * @returns {React.Component} -Third Party Button Styled
+ */
+function ThirdPartyButton({
+  img, alt, txt, onClick,
+}) {
+  return (
+    <ThirdPartyBtn variant="outlined" onClick={onClick}>
+      <ButtonIcon src={img} alt={alt} />
+      {txt}
+    </ThirdPartyBtn>
+  );
+}
+
+export default ThirdPartyButton;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_ThirdParty_thirdpartyServer.js.html b/docs/components_Authentication_ThirdParty_thirdpartyServer.js.html new file mode 100644 index 00000000..f32f9740 --- /dev/null +++ b/docs/components_Authentication_ThirdParty_thirdpartyServer.js.html @@ -0,0 +1,108 @@ + + + + + JSDoc: Source: components/Authentication/ThirdParty/thirdpartyServer.js + + + + + + + + + + +
+ +

Source: components/Authentication/ThirdParty/thirdpartyServer.js

+ + + + + + +
+
+
import { redirectHome } from '../../../utils/Redirect';
+import axios from '../../../services/instance';
+import { redditCookie } from '../authenticationServer';
+/**
+ * If Valid Token Then user is Logged in and redirected to the homepage
+ * @param {JsonResponse} googleResponse --Google Response
+ * @param {setFunction} setCookies --add Cookies
+ * @return {void}
+ */
+export const responseGoogleSuccess = (googleResponse, setCookies) => {
+  console.log('Google', googleResponse);
+  axios.post('/users/google', { tokenId: googleResponse.tokenId }).then((response) => {
+    if (response.status === 200 || response.status === 201) {
+      // success
+      // Add Reddit Cookie
+      redditCookie(setCookies);
+      redirectHome(1000);
+    }
+  }).catch((error) => {
+    if (error.response.status === 400) {
+      // ==>"status": "fail",
+      // ==>"message": "Token is invalid or has expired"
+      console.log(error);
+    }
+  });
+};
+
+/**
+ *
+ * @param {JsonResponse} googleResponse --Google Response
+ */
+export const responseGoogleFail = (googleResponse) => {
+  console.log('Error When Connecting to Google', googleResponse);
+};
+
+/**
+ *
+ * @param {JsonResponse} facebookResponse --Fcaebook Response
+ * @param {setFunction} setCookies --add Cookies* @return If Valid Token Then user is Logged in and redirected to the homepage
+ */
+export const responseFacebook = (facebookResponse, setCookies) => {
+  console.log('FaceBook', facebookResponse);
+  axios.post('/users/facebook', { access_token: facebookResponse.accessToken }).then((response) => {
+    if (response.status === 200 || response.status === 201) {
+      // success
+      // Add Reddit Cookie
+      redditCookie(setCookies);
+      redirectHome(1000);
+    }
+  }).catch((error) => {
+    if (error.response.status === 400) {
+      // ==>"status": "fail",
+      // ==>"message": "Token is invalid or has expired"
+      console.log(error);
+    }
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Authentication_authenticationServer.js.html b/docs/components_Authentication_authenticationServer.js.html new file mode 100644 index 00000000..432aed42 --- /dev/null +++ b/docs/components_Authentication_authenticationServer.js.html @@ -0,0 +1,192 @@ + + + + + JSDoc: Source: components/Authentication/authenticationServer.js + + + + + + + + + + +
+ +

Source: components/Authentication/authenticationServer.js

+ + + + + + +
+
+
// services
+import axios from '../../services/instance';
+
+// styles
+import { wrongIcon, rightIcon } from './styles';
+import theme from '../../styles/theme';
+
+// scripts
+// import { redirectLogin } from '../../utils/Redirect';
+
+// utils
+import { EmailFormat } from '../../utils/checkEmail';
+
+/**
+ * Remove Reddit Cookie
+ * @param {removecookiestate} removeCookie
+ */
+export const removeRedditCookie = (removeCookie) => {
+  removeCookie('redditUser');
+  // redirectLogin(0);
+};
+
+/**
+ *
+ * Add Reddit Cookie
+ * Must be Authorized user
+ * @returns {void}
+ */
+export const redditCookie = async (setCookie, removeCookie) => {
+  await axios.get('/users/me/').then((response) => {
+    console.log('Me in RedditCookie Response', response);
+    if (response.status === 200) {
+      console.log('Reddit Cokkie Added Again');
+      // set cookie
+      const date = new Date();
+      date.setDate(date.getDate() + 90);
+      setCookie('redditUser', response.data.user, { path: '/', expires: date });
+    }
+    // unauthorized(invalid JWT) =>Redirect to login page
+  }).catch((e) => {
+    // redirectLogin(20);
+    console.log('In Valid jwt');
+    console.log(e);
+    // Remove Reddit Cokkie if avaliable before
+    removeRedditCookie(removeCookie);
+  });
+};
+
+/**
+ *
+ * Check on Email Format
+ * @param {Srting} emailInput  --email input string
+ * @param {setfunction} setEmail  --setfunction for the Email Object
+ * @returns {void}
+ */
+export const checkEmail = (emailInput, setEmail) => {
+  if (emailInput === '') {
+    setEmail((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'Please enter an email address to continue',
+    }));
+  } else if (!EmailFormat(emailInput)) {
+    setEmail((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'Please fix your email to continue',
+    }));
+  } else {
+    setEmail((prevState) => ({
+      ...prevState,
+      color: theme.palette.primary.main,
+      icon: rightIcon,
+      error: null,
+    }));
+  }
+};
+
+/**
+ * check for Password Length more than 7 or not and change state of object atrributes accordingly
+ *
+ * @param {string} passwordInput --password to check on
+ * @param {setFunction} setPassword --setFunction for the password State
+ * @param {*} password --password object [undefined if not want to be used]
+ * @returns {void}
+ */
+export const checkPassword = (passwordInput, setPassword, password) => {
+  // console.log(passwordInput);
+  // console.log(password);// old value so New value must be passsed
+  // Check password more than 7
+  if (passwordInput === '' || passwordInput.length < 8) {
+    setPassword((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'Password must be at least 8 characters long',
+    }));
+    return;
+  }
+  // if Password is set to unaccepatble keep this
+  if (password !== undefined && password.error === 'This Password isn\'t acceptable' && password.score < 2) {
+    // still unchanged so keep
+    return;
+  }
+  // Accepeted
+  setPassword((prevState) => ({
+    ...prevState,
+    color: theme.palette.primary.main,
+    icon: rightIcon,
+    error: null,
+  }));
+};
+
+/**
+ * Check for Passwords matched or not
+ * @param {state} password
+ * @param {function} setPassword
+ * @returns {void}
+ */
+export const matchPassword = (passwordOne, passwordTwoInput, setPasswordTwo) => {
+  if (passwordOne.input !== passwordTwoInput) {
+    // console.log('Mismatch problem');
+    setPasswordTwo((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'Password must match',
+    }));
+    return;
+  }
+
+  // Accepeted
+  setPasswordTwo((prevState) => ({
+    ...prevState,
+    color: theme.palette.primary.main,
+    icon: rightIcon,
+    error: null,
+  }));
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_BackToTop_BackToTop.jsx.html b/docs/components_BackToTop_BackToTop.jsx.html new file mode 100644 index 00000000..c7e2cc76 --- /dev/null +++ b/docs/components_BackToTop_BackToTop.jsx.html @@ -0,0 +1,79 @@ + + + + + JSDoc: Source: components/BackToTop/BackToTop.jsx + + + + + + + + + + +
+ +

Source: components/BackToTop/BackToTop.jsx

+ + + + + + +
+
+
import { BackToTopButton, BackToTopContainer } from './styles';
+/**
+ * This component is the back to top button
+ *
+ * @component BackToTop
+ * @returns {React.Component} back to top button
+ */
+
+function BackToTop() {
+  const handelClick = () => {
+    window.scrollTo({
+      top: 0,
+    });
+  };
+  return (
+    <BackToTopContainer>
+      <BackToTopButton
+        variant="contained"
+        onClick={handelClick}
+        data-testid="back to top button"
+      >
+        back to top
+      </BackToTopButton>
+    </BackToTopContainer>
+  );
+}
+
+export default BackToTop;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_CreatePostContainer.jsx.html b/docs/components_CreatePost_CreatePostContainer_CreatePostContainer.jsx.html new file mode 100644 index 00000000..c9802061 --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_CreatePostContainer.jsx.html @@ -0,0 +1,155 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/CreatePostContainer.jsx + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/CreatePostContainer.jsx

+ + + + + + +
+
+
import { Box, useMediaQuery, useTheme } from '@mui/material';
+import { useCookies } from 'react-cookie';
+import { useEffect } from 'react';
+import { useParams } from 'react-router-dom';
+import getSubredditAllData from '../../SubReddit/SubrridetDataServer';
+import UserInfo from '../../MainProfile/Profile/MainContent/Sidebar/UserInfo/UserInfo';
+import { useCommunitiesInCreatePostContext } from '../../../contexts/CommunitiesInCreatePostContext';
+import MainContent from '../../MainContent/MainContent';
+import SideBar from '../../SideBar/SideBar';
+import CreatePostForm from './CreatePostForm/CreatePostForm';
+import SharePostForm from './SharePostForm/SharePostForm';
+import { MainContainer, OuterContainer } from './styles';
+import { useCreatePostSidebarContext } from '../../../contexts/CreatePostSidebarContext';
+import SubredditSideBar from '../../SubReddit/SideBar/SideBar';
+import PostingToReddit from './PostingToReddit/PostingToReddit';
+import CrosspostingToReddit from './CrosspostingToReddit/CrosspostingToReddit';
+/**
+ * This component works as a container for all create post page components
+ * and a repository the data fetched in
+ *
+ * @component CreatePostContainer
+ * @returns {React.Component} Container represents the create post page
+ */
+
+function CreatePostContainer() {
+  const theme = useTheme();
+  const match = useMediaQuery(theme.breakpoints.up('md'));
+
+  // params
+  const { source } = useParams();
+
+  // contexts
+  const { communities, communitiesError } = useCommunitiesInCreatePostContext();
+  const {
+    communityToPostIn, setCommunityToPostIn, ownerType, setOwnerType, communityName, setCommunityName,
+  } = useCreatePostSidebarContext();
+
+  console.log('oooowbbhdd', communityToPostIn, ownerType);
+  // cookies
+  const [cookies] = useCookies(['redditUser']);
+
+  // variables
+  const username = cookies.redditUser?.userName;
+  console.log('el comm elly fel', communityName?.substring(2), 'Nonlegit');
+  const [data] = getSubredditAllData(communityName?.substring(2));
+
+  useEffect(() => () => {
+    setCommunityToPostIn(null);
+    setOwnerType(null);
+    setCommunityName(null);
+  }, []);
+  console.log(source);
+  console.log('data from hosny', data);
+  return (
+    <OuterContainer>
+      <MainContainer>
+        <MainContent width={740}>
+          {!communitiesError ? (communities && (source ? <SharePostForm postId={source} /> : <CreatePostForm />)) : 'error in communities fetching'}
+        </MainContent>
+        {match
+        && (
+          (communityToPostIn === null || ownerType !== 'Subreddit') ? (
+            <SideBar>
+
+              <>
+                <Box
+                  margin={8}
+                />
+                {
+                    !(communityToPostIn === null || ownerType === null)
+                    && (
+                    <UserInfo
+                      username={username}
+                      createPost
+                    />
+                    )
+                  }
+                {!source
+                  ? <PostingToReddit />
+                  : <CrosspostingToReddit />}
+              </>
+
+            </SideBar>
+          ) : (
+            <SubredditSideBar
+              rules={data?.rules}
+              members={data?.membersCount}
+              Name={data?.fixedName}
+              username={username}
+              topics={data?.topics}
+              disc={data?.description}
+              primaryTopic={data?.primaryTopic}
+              createdAt={data?.createdAt}
+              moderatoesName={data?.moderators}
+              createPost
+            />
+          )
+        )}
+      </MainContainer>
+    </OuterContainer>
+  );
+}
+
+export default CreatePostContainer;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_CreatePostForm_CreatePostForm.jsx.html b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_CreatePostForm.jsx.html new file mode 100644 index 00000000..e619f64b --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_CreatePostForm.jsx.html @@ -0,0 +1,314 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/CreatePostForm/CreatePostForm.jsx + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/CreatePostForm/CreatePostForm.jsx

+ + + + + + +
+
+
import {
+  Box, Divider,
+} from '@mui/material';
+import '../../../../styles/theme/textEditor.css';
+import { useState, useEffect } from 'react';
+
+import { useNavigate, useParams } from 'react-router-dom';
+import {
+  FormContainer, Title, TitleContainer, DraftsButton, Badge, CustomDivider, PostFormContainer, FieldsContainer, PostTitle, PostUrl, WordCounter,
+} from './styles';
+import PostTags from './PostTags/PostTags';
+import PostSubmission from './PostSubmission/PostSubmission';
+import PostTypes from './PostTypes/PostTypes';
+import SubredditsMenu from './SubredditsMenu/SubredditsMenu';
+
+import { usePostTypeContext } from '../../../../contexts/PostTypeContext';
+import { useCreatePostSidebarContext } from '../../../../contexts/CreatePostSidebarContext';
+import submitPostServer from './submitPostServer';
+import currentSubredditServer from './currentSubredditServer';
+import TextEditor from './TextEditor/TextEditor';
+import PostMedia from './PostMedia/PostMedia';
+
+/**
+ * This component is the main section off create post page which holds the form to submit posts
+ *
+ * @component CreatePostForm
+ * @returns {React.Component} CreatePostForm
+ */
+
+function CreatePostForm() {
+  // routes
+  const { subredditName } = useParams();
+  const navigate = useNavigate();
+  // console.log(subredditName);
+
+  // server
+  const [subredditId, subredditIcon, initialOwnerType] = currentSubredditServer(subredditName);
+  // console.log('component', subredditId, subredditIcon, subredditName);
+
+  // contexts
+  const { initialPostType, initialPostUrl } = usePostTypeContext();
+  const {
+    communityToPostIn, setCommunityToPostIn, ownerType, setOwnerType, communityName, setCommunityName,
+  } = useCreatePostSidebarContext();
+
+  // variables
+  const postTypes = ['self', 'image', 'video', 'link'];
+
+  // states
+  const [postMedia, setPostMedia] = useState([]);
+  const [activeMediaFile, setActiveMediaFile] = useState(postMedia.length - 1);
+  const [title, setTitle] = useState('');
+  const [postText, setPostText] = useState('');
+  const [postUrl, setPostUrl] = useState(initialPostUrl);
+  const [postType, setPostType] = useState(initialPostType);
+  const [spoiler, setSpoiler] = useState(false);
+  const [nswf, setNswf] = useState(false);
+  const [sendReplies, setSendReplies] = useState(true);
+  const [flair, setFlair] = useState(null);
+  // console.log('title', title);
+  // console.log('community to post in', communityToPostIn);
+
+  useEffect(() => {
+    setCommunityToPostIn(subredditId);
+    setOwnerType(initialOwnerType);
+    setCommunityName(subredditName);
+  }, []);
+  useEffect(() => {
+    setCommunityToPostIn(subredditId);
+  }, [subredditId]);
+  /**
+   * This function check if server should send email to user as a reply to the post
+   */
+  const handleSendReplies = (e) => {
+    setSendReplies(e.target.checked);
+  };
+  // handlers
+
+  /**
+   * This function send post request to create post
+   */
+  const handlePost = (e) => {
+    e.preventDefault();
+    const post = {
+      title,
+      text: postText,
+      kind: postTypes[postType],
+      owner: communityToPostIn,
+      ownerType,
+      spoiler,
+      nswf,
+      sendReplies,
+      flairId: flair?.id,
+      flairText: flair?.text,
+      url: postUrl,
+    };
+    console.log('el post', post);
+    submitPostServer(post, navigate, postType, postMedia);
+  };
+  /**
+   * This function handles title change
+   */
+  const handleTitleChange = (e) => {
+    setTitle(e.target.value.substr(0, Math.min(300, e.target.value.length)));
+  };
+  /**
+   * This function handles post text change
+   */
+  // if (postText) { console.log(draftToHtml(convertToRaw(postText.getCurrentContent()))); }
+
+  const handlePostTextChange = (editorState) => {
+    console.log('editor', editorState);
+    setPostText(editorState);
+  };
+  const handleSaveDraft = (e) => {
+    e.preventDefault();
+  };
+  /**
+   * This function handles post type change
+   */
+  const handlePostType = (e, newPostType) => {
+    setPostType(newPostType);
+  };
+  /**
+   * This function handles post url change
+   */
+  const handleUrlChange = (e) => {
+    setPostUrl(e.target.value);
+  };
+  /**
+   * This function prevents user from type Enter in input fields
+   */
+  const handleEnter = (e) => {
+    if (e.key === 'Enter') {
+      e.preventDefault();
+    }
+  };
+  const handlePostMedia = (e) => {
+    console.log('ahmed sayed zizo', e.target.files);
+    setPostType(e.target.files[0].type.substr(0, 5) === 'video' ? 2 : 1);
+    const files = Array.from(e.target.files).map((file) => ({
+      src: URL.createObjectURL(file),
+      caption: '',
+      link: '',
+      file,
+      fileName: file.name,
+    }));
+    setActiveMediaFile(postMedia.length + files.length - 1);
+    setPostMedia([...postMedia, ...files]);
+  };
+  console.log(postMedia);
+  /**
+   * This function handles if post is spoiler or not
+   */
+  const hanldeSpoiler = () => {
+    setSpoiler(!spoiler);
+  };
+  /**
+   * This function handles if post is not safe for work or not
+   */
+  const hanldeNsfw = () => {
+    setNswf(!nswf);
+  };
+
+  console.log('post text', postText);
+  return (
+    <FormContainer>
+      <TitleContainer my={2}>
+        <Title variant="h6">
+          Create a post
+        </Title>
+        <DraftsButton color="third" padding="4px 16px" fontSize={12} fontWeight="bold">
+          drafts
+          <Badge>
+            0
+          </Badge>
+        </DraftsButton>
+      </TitleContainer>
+      <CustomDivider />
+      <SubredditsMenu
+        setCommunityToPostIn={setCommunityToPostIn}
+        setOwnerType={setOwnerType}
+        subredditIcon={subredditIcon}
+        subredditName={subredditName}
+        ownerType={ownerType}
+        communityName={communityName}
+        setCommunityName={setCommunityName}
+        setFlair={setFlair}
+      />
+      <PostFormContainer>
+        <PostTypes
+          postType={postType}
+          handlePostType={handlePostType}
+        />
+        <FieldsContainer>
+          <Box
+            position="relative"
+            display="flex"
+            flexDirection="column"
+            marginBottom={2}
+          >
+            <PostTitle
+              type="text"
+              placeholder="Title"
+              value={title}
+              onChange={handleTitleChange}
+              onKeyDown={handleEnter}
+            />
+            <WordCounter>
+              {title.length}
+              /300
+            </WordCounter>
+          </Box>
+          {postType === 0 ? (
+            <TextEditor
+              handlePostTextChange={handlePostTextChange}
+              postText={postText}
+              id="create"
+            />
+          ) : null}
+          {(postType === 1 || postType === 2) ? (
+            <PostMedia
+              handlePostMedia={handlePostMedia}
+              postMedia={postMedia}
+              setPostMedia={setPostMedia}
+              activeMediaFile={activeMediaFile}
+              setActiveMediaFile={setActiveMediaFile}
+              availableType={postType === 1 ? 'image' : 'video'}
+            />
+          ) : null}
+          {postType === 3 ? (
+            <PostUrl
+              placeholder="Url"
+              value={postUrl}
+              onChange={handleUrlChange}
+              onKeyDown={handleEnter}
+            />
+          ) : null}
+        </FieldsContainer>
+        <PostTags
+          spoiler={spoiler}
+          hanldeSpoiler={hanldeSpoiler}
+          nswf={nswf}
+          hanldeNsfw={hanldeNsfw}
+          setFlair={setFlair}
+          subreddit={communityName?.substring(2)}
+          flair={flair}
+          communityName={communityName}
+        />
+        <Divider />
+        <PostSubmission
+          handleSaveDraft={handleSaveDraft}
+          handlePost={handlePost}
+          readyToPost={communityToPostIn != null && title}
+          handleSendReplies={handleSendReplies}
+          sendReplies={sendReplies}
+        />
+      </PostFormContainer>
+    </FormContainer>
+  );
+}
+
+export default CreatePostForm;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_CreatePostForm_PostSubmission_PostSubmission.jsx.html b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_PostSubmission_PostSubmission.jsx.html new file mode 100644 index 00000000..2b52aec3 --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_PostSubmission_PostSubmission.jsx.html @@ -0,0 +1,119 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/CreatePostForm/PostSubmission/PostSubmission.jsx + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/CreatePostForm/PostSubmission/PostSubmission.jsx

+ + + + + + +
+
+
import { Box, Checkbox } from '@mui/material';
+import RedditButton from '../../../../RedditButton/RedditButton';
+import {
+  ConnectAccounts, InfoIcon, PostButton, SendReplayFormLabel, SendReplyContainer,
+} from './styles';
+/**
+ * This component contains post and save draft buttons
+ *
+ * @component PostHeader
+ * @property {function} handleSaveDraft -Hanlding save draft button
+ * @property {function} handlePost -Hanlding post submitting
+ * @property {boolean} readyToPost -Check whether the post button is disabled or not
+ * @property {boolean} sendReplies -Check whether the user need to be sent the post reply notifications or not.
+ * @property {function} handleSendReplies -Hanlding post reply notifications
+ * @returns {React.Component} Container of buttons
+ */
+
+function PostSubmission(props) {
+  const {
+    handleSaveDraft, handlePost, readyToPost, handleSendReplies, sendReplies,
+  } = props;
+  return (
+    <Box>
+      <Box m={2} gap={1} display="flex" justifyContent="flex-end">
+        <RedditButton
+          variant="outlined"
+          padding="3px 16px"
+          fontSize={14}
+          fontWeight="bold"
+          type="submit"
+          onClick={handleSaveDraft}
+        >
+          save draft
+        </RedditButton>
+        <PostButton
+          variant="contained"
+          type="submit"
+          onClick={handlePost}
+          disabled={!readyToPost}
+          data-testid="post button"
+        >
+          post
+        </PostButton>
+      </Box>
+      <SendReplyContainer p={2}>
+        <SendReplayFormLabel
+          control={(
+            <Checkbox
+              onChange={handleSendReplies}
+              checked={sendReplies}
+              size="small"
+              disableRipple
+            />
+)}
+          label="Send me post reply notifications"
+        />
+        <Box display="flex">
+          <ConnectAccounts>
+            Connect accounts to share your post
+          </ConnectAccounts>
+          <InfoIcon />
+        </Box>
+      </SendReplyContainer>
+    </Box>
+  );
+}
+
+export default PostSubmission;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_CreatePostForm_PostTags_PostTags.jsx.html b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_PostTags_PostTags.jsx.html new file mode 100644 index 00000000..8617d874 --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_PostTags_PostTags.jsx.html @@ -0,0 +1,207 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/CreatePostForm/PostTags/PostTags.jsx + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/CreatePostForm/PostTags/PostTags.jsx

+ + + + + + +
+
+
import AddIcon from '@mui/icons-material/Add';
+import LocalOfferOutlinedIcon from '@mui/icons-material/LocalOfferOutlined';
+import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
+import {
+  Box, useMediaQuery, useTheme,
+} from '@mui/material';
+import { useState } from 'react';
+import {
+  CustomTooltip, NsfwButton, OptionButton, SpoilerButton,
+} from './styles';
+import Flairs from './Flairs/Flairs';
+import flairsServer from './flairsServer';
+/**
+ * This component is post tags
+ *
+ * @component PostTags
+ * @property {boolean} spoiler -Check whether the post is spoiler or not.
+ * @property {function} hanldeSpoiler -function to handle click on spoiler button
+ * @property {boolean} nswf -Check whether the post is not safe for work or not.
+ * @property {function} hanldeNsfw -function to handle click on nsfw button
+ * @returns {React.Component} Join button
+ */
+
+function PostTags(props) {
+  const {
+    spoiler, hanldeSpoiler, nswf, hanldeNsfw, setFlair, subreddit, flair, communityName,
+  } = props;
+  const theme = useTheme();
+  const match = useMediaQuery(theme.breakpoints.down('sm'));
+
+  // states
+  const [openFlairs, setOpenFlairs] = useState(false);
+
+  // services
+  const [flairs, flairsError] = flairsServer(subreddit);
+  // console.log('flairs', flairs);
+
+  // handlers
+  const handleOpenFlairs = (value) => {
+    setOpenFlairs(value);
+    // console.log('value', value);
+  };
+  // console.log(flair);
+  return (
+    <Box
+      display="flex"
+      flexWrap="wrap"
+      mx={2}
+      mb={2}
+      gap={1}
+      justifyContent={match ? 'center' : 'flex-start'}
+    >
+      <CustomTooltip
+        title="Mark as a spoiler"
+        placement="top"
+        arrow
+        disableInteractive
+        leaveTouchDelay={0}
+        enterDelay={500}
+        enterNextDelay={500}
+      >
+        <SpoilerButton
+          variant="outlined"
+          color="third"
+          onClick={hanldeSpoiler}
+          spoiler={spoiler}
+          data-testid="spoiler button"
+        >
+          <AddIcon
+            sx={{
+              fontSize: 27,
+              marginRight: 0.6,
+            }}
+          />
+          spoiler
+        </SpoilerButton>
+      </CustomTooltip>
+      <CustomTooltip
+        title="Mark as Not Safe For Work"
+        placement="top"
+        arrow
+        disableInteractive
+        leaveTouchDelay={0}
+        enterDelay={500}
+        enterNextDelay={500}
+      >
+        <NsfwButton
+          color="third"
+          variant={!nswf ? 'outlined' : ''}
+          onClick={hanldeNsfw}
+          nswf={nswf}
+          data-testid="nsfw button"
+        >
+          <AddIcon
+            sx={{
+              fontSize: 27,
+              marginRight: 0.6,
+            }}
+          />
+          NSFW
+        </NsfwButton>
+      </CustomTooltip>
+      <CustomTooltip
+        title={flairs ? (flair ? 'Change or remove flair' : 'Add flair') : 'Not available for this community'}
+        placement="top"
+        arrow
+        disableInteractive
+        leaveTouchDelay={0}
+        enterDelay={500}
+        enterNextDelay={500}
+      >
+        <Box
+          display="flex"
+          sx={{
+            cursor: 'not-allowed',
+          }}
+        >
+          <OptionButton
+            color={!flair ? 'third' : ''}
+            variant={!flair ? 'outlined' : ''}
+            onClick={() => handleOpenFlairs(true)}
+            disabled={!subreddit || flairsError || !flairs}
+            flair={flair}
+          >
+            <LocalOfferOutlinedIcon
+              sx={{
+                marginRight: 1,
+                transform: 'scalex(-1)',
+              }}
+            />
+            <Box sx={{
+              maxWidth: 130,
+              whiteSpace: 'nowrap',
+              overflow: 'hidden',
+              textOverflow: 'ellipsis',
+            }}
+            >
+              {flair ? flair.text : 'flair' }
+            </Box>
+            <KeyboardArrowDownOutlinedIcon />
+          </OptionButton>
+        </Box>
+      </CustomTooltip>
+      <Flairs
+        open={openFlairs}
+        handleOpenFlairs={handleOpenFlairs}
+        setFlair={setFlair}
+        flairs={flairs}
+        flair={flair}
+        communityName={communityName}
+      />
+    </Box>
+  );
+}
+
+export default PostTags;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_CreatePostForm_PostTypes_PostTypes.jsx.html b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_PostTypes_PostTypes.jsx.html new file mode 100644 index 00000000..7e0b62e4 --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_PostTypes_PostTypes.jsx.html @@ -0,0 +1,120 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/CreatePostForm/PostTypes/PostTypes.jsx + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/CreatePostForm/PostTypes/PostTypes.jsx

+ + + + + + +
+
+
import { Divider } from '@mui/material';
+import PostAddOutlinedIcon from '@mui/icons-material/PostAddOutlined';
+import ImageOutlinedIcon from '@mui/icons-material/ImageOutlined';
+import AttachFileIcon from '@mui/icons-material/AttachFile';
+import { useEffect, useState } from 'react';
+import { CustomTab, CustomTabs } from './styles';
+/**
+ * This component contains the tabs of post types
+ *
+ * @component PostTypes
+ * @property {function} postType -Post type (text, image, video and url).
+ * @property {function} handlePostType -Hanlding post type.
+ * @returns {React.Component} tabs of post types
+ */
+
+function PostTypes(props) {
+  const { postType, handlePostType } = props;
+  const [lastMediaType, setLastMediaType] = useState(postType === 2 ? 2 : 1);
+  useEffect(() => {
+    if (postType === 2 || postType === 1) {
+      setLastMediaType(postType);
+    }
+  }, [postType]);
+
+  return (
+    <CustomTabs
+      value={postType}
+      onChange={handlePostType}
+    >
+      <CustomTab
+        icon={<PostAddOutlinedIcon />}
+        iconPosition="start"
+        label="post"
+        value={0}
+        data-testid="text"
+      />
+      <Divider
+        orientation="vertical"
+        flexItem
+        light
+      />
+      <CustomTab
+        icon={<ImageOutlinedIcon />}
+        iconPosition="start"
+        label="images & videos"
+        value={lastMediaType}
+        data-testid="media"
+      />
+      <Divider
+        orientation="vertical"
+        flexItem
+        light
+      />
+      <CustomTab
+        icon={(
+          <AttachFileIcon
+            sx={{ transform: 'rotate(45deg)' }}
+          />
+)}
+        iconPosition="start"
+        label="link"
+        value={3}
+        data-testid="url"
+      />
+    </CustomTabs>
+  );
+}
+
+export default PostTypes;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_CreatePostForm_SubredditsMenu_SubredditsMenu.jsx.html b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_SubredditsMenu_SubredditsMenu.jsx.html new file mode 100644 index 00000000..21c31042 --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_SubredditsMenu_SubredditsMenu.jsx.html @@ -0,0 +1,269 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/CreatePostForm/SubredditsMenu/SubredditsMenu.jsx + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/CreatePostForm/SubredditsMenu/SubredditsMenu.jsx

+ + + + + + +
+
+
import {
+  Box,
+  ClickAwayListener,
+  Divider, ListItem,
+} from '@mui/material';
+import { useState, useEffect } from 'react';
+import { useCookies } from 'react-cookie';
+import { useCommunitiesInCreatePostContext } from '../../../../../contexts/CommunitiesInCreatePostContext';
+import iMatcher from '../../../../../utils/iMatcher';
+import numberWithCommas from '../../../../../utils/numberWithCommas';
+import RedditButton from '../../../../RedditButton/RedditButton';
+import {
+  AvatarContainer, CommunityCategory, CustomList, DashedCircle, DropIcon, MenuContainer, MenuOuterContainer, SubredditsContainer, SubredditSearchField, CustomAvatar, CommunityName, CommunityAvatar, Members, CommunityContainer, SearchIcon, NoCommunitiesFound, ChosenCommunityIcon, ClickAwayContainer,
+} from './styles';
+
+/**
+ * This component contains the menu of subreddit that the use can post in
+ *
+ * @component SubredditsMenu
+ * @property {function} setCommunityToPostIn -Hanlding post owner (ID).
+ * @property {function} setOwnerType -Hanlding post owner type (subreddit or user).
+ * @property {string} subredditIcon -Subreddit icon.
+ * @property {string} subredditName -Subreddit name.
+ * @property {string} ownerType -to know if the type of the owner is User or Subreddit
+ * @returns {React.Component} Container of subreddit menu
+ */
+
+function SubredditsMenu(props) {
+  // props
+  const {
+    setCommunityToPostIn, setOwnerType, subredditIcon, subredditName, ownerType, communityName, setCommunityName, setFlair,
+  } = props;
+
+  // contexts
+  const { communities } = useCommunitiesInCreatePostContext();
+
+  // states
+  const [open, setOpen] = useState(false);
+  const [searching, setSearching] = useState(false);
+  const [chosenCommunityIcon, setChosenCommunityIcon] = useState(subredditIcon);
+  const [showIcon, setShowIcon] = useState(!!subredditName);
+  // console.log('show icon', showIcon);
+  // console.log(chosenCommunityIcon);
+
+  useEffect(() => {
+    setChosenCommunityIcon(subredditIcon);
+    setCommunityName(subredditName && `r/${subredditName}`);
+  }, [subredditIcon, subredditName]);
+
+  // cookies
+  const [cookies] = useCookies(['redditUser']);
+
+  // handlers
+  const handleClickOnChoose = () => {
+    setOpen(true);
+    setSearching(true);
+    setChosenCommunityIcon(null);
+    setCommunityToPostIn(null);
+    setFlair(null);
+  };
+  const handleClickAway = () => {
+    setOpen(false);
+    setSearching(false);
+    setShowIcon(true);
+  };
+  const handleDrop = () => {
+    if (open) {
+      setSearching(true);
+      setOpen(false);
+    } else {
+      setOpen(true);
+      setSearching(true);
+    }
+  };
+  const chooseCommunity = (communityId, communityName, icon, ownerType) => {
+    setCommunityToPostIn(communityId);
+    setOwnerType(ownerType);
+    console.log('el comm elly', communityName);
+    setCommunityName(communityName);
+    setOpen(false);
+    setChosenCommunityIcon(icon);
+  };
+  const handleCommunityNameChange = (e) => {
+    setCommunityName(e.target.value);
+    setChosenCommunityIcon(null);
+  };
+  const handleFilter = (community) => iMatcher(`r/${community.subredditName}`, communityName);
+  // console.log(communityName);
+
+  // variables
+  const filteredArray = communities?.filter(handleFilter);
+  const filteredCommunities = filteredArray?.length === 0 ? null : filteredArray;
+  const username = cookies.redditUser?.userName;
+  const profileMatching = iMatcher(`u/${username}`, communityName);
+  const userIcon = cookies.redditUser?.profilePicture;
+
+  return (
+    <MenuOuterContainer>
+      <ClickAwayListener onClickAway={handleClickAway}>
+        <ClickAwayContainer>
+          <MenuContainer>
+            {searching ? <SearchIcon />
+              : (showIcon && chosenCommunityIcon
+                ? (
+                  <ChosenCommunityIcon
+                    src={chosenCommunityIcon}
+                    ownerType={ownerType}
+                  >
+                    {ownerType === 'Subreddit' ? 'r/' : (ownerType === 'User' ? 'u/' : '')}
+                  </ChosenCommunityIcon>
+                ) : <DashedCircle />)}
+            <SubredditSearchField
+              type="text"
+              placeholder={searching ? 'Search communities' : 'Choose a community'}
+              onClick={handleClickOnChoose}
+              value={communityName}
+              onChange={handleCommunityNameChange}
+            />
+            <DropIcon onClick={handleDrop} />
+          </MenuContainer>
+          {open
+          && searching
+          && (
+          <SubredditsContainer>
+            { profileMatching
+            && (
+            <>
+              <CommunityCategory padding="16px 16px 4px">
+                your profile
+              </CommunityCategory>
+              <CustomList>
+                <ListItem
+                  sx={{ cursor: 'pointer' }}
+                  onClick={() => chooseCommunity(0, `u/${username}`, userIcon, 'User')}
+                >
+                  <AvatarContainer>
+                    <CustomAvatar
+                      src={userIcon}
+                      alt="avatar"
+                      variant="square"
+                    >
+                      u/
+                    </CustomAvatar>
+                  </AvatarContainer>
+                  <CommunityContainer>
+                    <CommunityName>
+                      u/
+                      {username}
+                    </CommunityName>
+                  </CommunityContainer>
+                </ListItem>
+              </CustomList>
+              {(profileMatching && filteredCommunities) && <Divider />}
+            </>
+            )}
+            {!filteredCommunities && !profileMatching && (
+            <NoCommunitiesFound>
+              No communities found
+            </NoCommunitiesFound>
+            )}
+            {(!profileMatching || filteredCommunities) && (
+            <Box
+              display="flex"
+              justifyContent="space-between"
+              padding="8px 8px 3px 16px"
+              alignItems="center"
+            >
+              <CommunityCategory>
+                your communities
+              </CommunityCategory>
+              <RedditButton
+                padding="2px 8px"
+                fontSize={12}
+                fontWeight={700}
+              >
+                create new
+              </RedditButton>
+            </Box>
+            )}
+
+            <CustomList>
+              {(filteredCommunities || (profileMatching ? [] : communities))?.map((community) => {
+                const {
+                  id, subredditName, membersCount, icon,
+                } = community;
+                return (
+                  <ListItem
+                    key={id}
+                    sx={{ cursor: 'pointer' }}
+                    onClick={() => chooseCommunity(id, `r/${subredditName}`, icon, 'Subreddit')}
+                  >
+                    <CommunityAvatar src={icon}>
+                      r/
+                    </CommunityAvatar>
+                    <CommunityContainer>
+                      <CommunityName>
+                        r/
+                        {subredditName}
+                      </CommunityName>
+                      <Members>
+                        {numberWithCommas(membersCount)}
+                        {' '}
+                        members
+                      </Members>
+                    </CommunityContainer>
+                  </ListItem>
+                );
+              })}
+            </CustomList>
+            <Divider />
+          </SubredditsContainer>
+          )}
+        </ClickAwayContainer>
+      </ClickAwayListener>
+    </MenuOuterContainer>
+  );
+}
+export default SubredditsMenu;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_CreatePostForm_currentSubredditServer.js.html b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_currentSubredditServer.js.html new file mode 100644 index 00000000..561b4e90 --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_currentSubredditServer.js.html @@ -0,0 +1,72 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/CreatePostForm/currentSubredditServer.js + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/CreatePostForm/currentSubredditServer.js

+ + + + + + +
+
+
/**
+ * This function works as a server create post page
+ *
+ * @function createPostServerforSubreddit
+ */
+
+import getSubredditAllData from '../../../SubReddit/SubrridetDataServer';
+
+const currentSubredditServer = (subredditName) => {
+  if (!subredditName) {
+    return [null, null, ''];
+  }
+  const [data] = getSubredditAllData(subredditName);
+  console.log(data);
+  const subredditId = data?._id;
+  const subredditIcon = data?.icon;
+  console.log('server', subredditId, subredditIcon, subredditName);
+  return [subredditId, subredditIcon, 'Subreddit'];
+};
+
+export default currentSubredditServer;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_CreatePostForm_submitPostServer.js.html b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_submitPostServer.js.html new file mode 100644 index 00000000..40eef067 --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_CreatePostForm_submitPostServer.js.html @@ -0,0 +1,111 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/CreatePostForm/submitPostServer.js + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/CreatePostForm/submitPostServer.js

+ + + + + + +
+
+
import axiosMedia from '../../../../services/mediaInstance';
+import axios from '../../../../services/instance';
+import { redirectLogin } from '../../../../utils/Redirect';
+/**
+ * This function works as a server for submitting post
+ *
+ * @function submitPostServer
+ * @param {Object} post - post to be posted
+ */
+
+// eslint-disable-next-line no-unused-vars
+const submitPostServer = (post, navigate, postType, postMedia) => {
+  console.log('fawzy', JSON.stringify(post));
+  axios.post('/posts', JSON.stringify(post)).then((response) => {
+    console.log(response.data);
+    console.log(response.status);
+    console.log('env variable', process.env.REACT_APP_ENV);
+    if (response.status !== 201) {
+      if (response.status === 401) {
+        redirectLogin();
+      }
+      const { message } = response.data;
+      console.log(message);
+    } else {
+      const post = response?.data?.data;
+      console.log('response after create post', post);
+      console.log('post from response', post);
+      const postId = post?._id;
+      console.log('post from response', postId);
+      if (postType === 1 || postType === 2) {
+        postMedia.forEach((media) => {
+          const formData = new FormData();
+          const { fileName, file } = media;
+          formData.append('filename', fileName);
+          formData.append('file', file);
+          formData.append('kind', postType === 1 ? 'image' : 'video');
+          console.log(formData);
+          console.log('data adddddddddddddddddddddddddddddddddddddddddd');
+          axiosMedia.post(`/posts/${postId}/images`, formData).then((response) => {
+            console.log('after media', response);
+          }).catch((error) => {
+            console.log(error.response);
+            console.log(error.response.status);
+            console.log(error.response.message);
+            alert('somethig went wrong with creating images');
+          });
+        });
+      }
+      alert('posted successfully');
+      navigate('/');
+    }
+  }).catch((e) => {
+    console.log(e.response);
+    console.log(e.response.status);
+    console.log(e.response.message);
+    alert('somethig went wrong');
+  });
+};
+
+export default submitPostServer;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_SharePostForm_PostSubmission_PostSubmission.jsx.html b/docs/components_CreatePost_CreatePostContainer_SharePostForm_PostSubmission_PostSubmission.jsx.html new file mode 100644 index 00000000..e2ed6585 --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_SharePostForm_PostSubmission_PostSubmission.jsx.html @@ -0,0 +1,119 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/SharePostForm/PostSubmission/PostSubmission.jsx + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/SharePostForm/PostSubmission/PostSubmission.jsx

+ + + + + + +
+
+
import { Box, Checkbox } from '@mui/material';
+import RedditButton from '../../../../RedditButton/RedditButton';
+import {
+  ConnectAccounts, InfoIcon, PostButton, SendReplayFormLabel, SendReplyContainer,
+} from './styles';
+/**
+ * This component contains post and save draft buttons
+ *
+ * @component PostHeader
+ * @property {function} handleSaveDraft -Hanlding save draft button
+ * @property {function} handlePost -Hanlding post submitting
+ * @property {boolean} readyToPost -Check whether the post button is disabled or not
+ * @property {boolean} sendReplies -Check whether the user need to be sent the post reply notifications or not.
+ * @property {function} handleSendReplies -Hanlding post reply notifications
+ * @returns {React.Component} Container of buttons
+ */
+
+function PostSubmission(props) {
+  const {
+    handleSaveDraft, handlePost, readyToPost, handleSendReplies, sendReplies,
+  } = props;
+  return (
+    <Box>
+      <Box m={2} gap={1} display="flex" justifyContent="flex-end">
+        <RedditButton
+          variant="outlined"
+          padding="3px 16px"
+          fontSize={14}
+          fontWeight="bold"
+          type="submit"
+          onClick={handleSaveDraft}
+        >
+          save draft
+        </RedditButton>
+        <PostButton
+          variant="contained"
+          type="submit"
+          onClick={handlePost}
+          disabled={!readyToPost}
+          data-testid="post button"
+        >
+          post
+        </PostButton>
+      </Box>
+      <SendReplyContainer p={2}>
+        <SendReplayFormLabel
+          control={(
+            <Checkbox
+              onChange={handleSendReplies}
+              checked={sendReplies}
+              size="small"
+              disableRipple
+            />
+)}
+          label="Send me post reply notifications"
+        />
+        <Box display="flex">
+          <ConnectAccounts>
+            Connect accounts to share your post
+          </ConnectAccounts>
+          <InfoIcon />
+        </Box>
+      </SendReplyContainer>
+    </Box>
+  );
+}
+
+export default PostSubmission;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_SharePostForm_PostTags_PostTags.jsx.html b/docs/components_CreatePost_CreatePostContainer_SharePostForm_PostTags_PostTags.jsx.html new file mode 100644 index 00000000..4130a58d --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_SharePostForm_PostTags_PostTags.jsx.html @@ -0,0 +1,207 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/SharePostForm/PostTags/PostTags.jsx + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/SharePostForm/PostTags/PostTags.jsx

+ + + + + + +
+
+
import AddIcon from '@mui/icons-material/Add';
+import LocalOfferOutlinedIcon from '@mui/icons-material/LocalOfferOutlined';
+import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
+import {
+  Box, useMediaQuery, useTheme,
+} from '@mui/material';
+import { useState } from 'react';
+import {
+  CustomTooltip, NsfwButton, OptionButton, SpoilerButton,
+} from './styles';
+import Flairs from './Flairs/Flairs';
+import flairsServer from './flairsServer';
+/**
+ * This component is post tags
+ *
+ * @component PostTags
+ * @property {boolean} spoiler -Check whether the post is spoiler or not.
+ * @property {function} hanldeSpoiler -function to handle click on spoiler button
+ * @property {boolean} nswf -Check whether the post is not safe for work or not.
+ * @property {function} hanldeNsfw -function to handle click on nsfw button
+ * @returns {React.Component} Join button
+ */
+
+function PostTags(props) {
+  const {
+    spoiler, hanldeSpoiler, nswf, hanldeNsfw, setFlair, subreddit, flair, communityName,
+  } = props;
+  const theme = useTheme();
+  const match = useMediaQuery(theme.breakpoints.down('sm'));
+
+  // states
+  const [openFlairs, setOpenFlairs] = useState(false);
+
+  // services
+  const [flairs, flairsError] = flairsServer(subreddit);
+  // console.log('flairs', flairs);
+
+  // handlers
+  const handleOpenFlairs = (value) => {
+    setOpenFlairs(value);
+    // console.log('value', value);
+  };
+  // console.log(flair);
+  return (
+    <Box
+      display="flex"
+      flexWrap="wrap"
+      mx={2}
+      mb={2}
+      gap={1}
+      justifyContent={match ? 'center' : 'flex-start'}
+    >
+      <CustomTooltip
+        title="Mark as a spoiler"
+        placement="top"
+        arrow
+        disableInteractive
+        leaveTouchDelay={0}
+        enterDelay={500}
+        enterNextDelay={500}
+      >
+        <SpoilerButton
+          variant="outlined"
+          color="third"
+          onClick={hanldeSpoiler}
+          spoiler={spoiler}
+          data-testid="spoiler button"
+        >
+          <AddIcon
+            sx={{
+              fontSize: 27,
+              marginRight: 0.6,
+            }}
+          />
+          spoiler
+        </SpoilerButton>
+      </CustomTooltip>
+      <CustomTooltip
+        title="Mark as Not Safe For Work"
+        placement="top"
+        arrow
+        disableInteractive
+        leaveTouchDelay={0}
+        enterDelay={500}
+        enterNextDelay={500}
+      >
+        <NsfwButton
+          color="third"
+          variant={!nswf ? 'outlined' : ''}
+          onClick={hanldeNsfw}
+          nswf={nswf}
+          data-testid="nsfw button"
+        >
+          <AddIcon
+            sx={{
+              fontSize: 27,
+              marginRight: 0.6,
+            }}
+          />
+          NSFW
+        </NsfwButton>
+      </CustomTooltip>
+      <CustomTooltip
+        title={flairs ? (flair ? 'Change or remove flair' : 'Add flair') : 'Not available for this community'}
+        placement="top"
+        arrow
+        disableInteractive
+        leaveTouchDelay={0}
+        enterDelay={500}
+        enterNextDelay={500}
+      >
+        <Box
+          display="flex"
+          sx={{
+            cursor: 'not-allowed',
+          }}
+        >
+          <OptionButton
+            color={!flair ? 'third' : ''}
+            variant={!flair ? 'outlined' : ''}
+            onClick={() => handleOpenFlairs(true)}
+            disabled={!subreddit || flairsError || !flairs}
+            flair={flair}
+          >
+            <LocalOfferOutlinedIcon
+              sx={{
+                marginRight: 1,
+                transform: 'scalex(-1)',
+              }}
+            />
+            <Box sx={{
+              maxWidth: 130,
+              whiteSpace: 'nowrap',
+              overflow: 'hidden',
+              textOverflow: 'ellipsis',
+            }}
+            >
+              {flair ? flair.text : 'flair' }
+            </Box>
+            <KeyboardArrowDownOutlinedIcon />
+          </OptionButton>
+        </Box>
+      </CustomTooltip>
+      <Flairs
+        open={openFlairs}
+        handleOpenFlairs={handleOpenFlairs}
+        setFlair={setFlair}
+        flairs={flairs}
+        flair={flair}
+        communityName={communityName}
+      />
+    </Box>
+  );
+}
+
+export default PostTags;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_SharePostForm_SharePostForm.jsx.html b/docs/components_CreatePost_CreatePostContainer_SharePostForm_SharePostForm.jsx.html new file mode 100644 index 00000000..fd8a6c78 --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_SharePostForm_SharePostForm.jsx.html @@ -0,0 +1,251 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/SharePostForm/SharePostForm.jsx + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/SharePostForm/SharePostForm.jsx

+ + + + + + +
+
+
import {
+  Box, Divider,
+} from '@mui/material';
+import '../../../../styles/theme/textEditor.css';
+import { useState, useEffect } from 'react';
+
+import { useNavigate, useParams } from 'react-router-dom';
+import {
+  FormContainer, Title, TitleContainer, DraftsButton, Badge, CustomDivider, PostFormContainer, FieldsContainer, PostTitle, WordCounter,
+} from './styles';
+import PostTags from './PostTags/PostTags';
+import PostSubmission from './PostSubmission/PostSubmission';
+import SubredditsMenu from './SubredditsMenu/SubredditsMenu';
+import { useCreatePostSidebarContext } from '../../../../contexts/CreatePostSidebarContext';
+import currentSubredditServer from './currentSubredditServer';
+import getPostServer from './getPostServer';
+import SharedPost from '../../../Post/SharedPost/SharedPost';
+import sharePostServer from './sharePostServer';
+
+/**
+ * This component is the main section off create post page which holds the form to submit posts
+ *
+ * @component CreatePostForm
+ * @returns {React.Component} CreatePostForm
+ */
+
+function CreatePostForm(props) {
+  // props
+  const { postId } = props;
+
+  // routes
+  const navigate = useNavigate();
+  const { subredditName } = useParams();
+  // console.log(subredditName);
+
+  // server
+  const [subredditId, subredditIcon, initialOwnerType] = currentSubredditServer(subredditName);
+  // console.log('component', subredditId, subredditIcon, subredditName);
+
+  // contexts
+  const {
+    communityToPostIn, setCommunityToPostIn, ownerType, setOwnerType, communityName, setCommunityName,
+  } = useCreatePostSidebarContext();
+
+  // states
+  const [title, setTitle] = useState('');
+  const [spoiler, setSpoiler] = useState(false);
+  const [nswf, setNswf] = useState(false);
+  const [sendReplies, setSendReplies] = useState(true);
+  const [flair, setFlair] = useState(null);
+
+  const [parentPost, error] = getPostServer(postId);
+
+  useEffect(() => {
+    setCommunityToPostIn(subredditId);
+    setOwnerType(initialOwnerType);
+    setCommunityName(subredditName);
+  }, []);
+  useEffect(() => {
+    setCommunityToPostIn(subredditId);
+  }, [subredditId]);
+  useEffect(() => {
+    if (parentPost) {
+      setTitle(parentPost.title);
+    }
+  }, [parentPost]);
+  /**
+   * This function check if server should send email to user as a reply to the post
+   */
+  const handleSendReplies = (e) => {
+    setSendReplies(e.target.checked);
+  };
+  // handlers
+
+  /**
+   * This function send post request to create post
+   */
+  const handlePost = (e) => {
+    e.preventDefault();
+    console.log('share', e);
+    const post = {
+      title,
+      owner: communityToPostIn,
+      ownerType,
+      spoiler,
+      nswf,
+      sendReplies,
+      flairId: flair?.id,
+      flairText: flair?.text,
+      sharedFrom: postId,
+    };
+    console.log('el post', post);
+    sharePostServer(post, navigate);
+  };
+  /**
+   * This function handles title change
+   */
+  const handleTitleChange = (e) => {
+    setTitle(e.target.value.substr(0, Math.min(300, e.target.value.length)));
+  };
+  /**
+   * This function handles post text change
+   */
+  const handleSaveDraft = (e) => {
+    e.preventDefault();
+  };
+  /**
+   * This function prevents user from type Enter in input fields
+   */
+  const handleEnter = (e) => {
+    if (e.key === 'Enter') {
+      e.preventDefault();
+    }
+  };
+  /**
+   * This function handles if post is spoiler or not
+   */
+  const hanldeSpoiler = () => {
+    setSpoiler(!spoiler);
+  };
+  /**
+   * This function handles if post is not safe for work or not
+   */
+  const hanldeNsfw = () => {
+    setNswf(!nswf);
+  };
+
+  return (
+    !error && parentPost
+      ? (
+        <FormContainer>
+          <TitleContainer my={2}>
+            <Title variant="h6">
+              Create a post
+            </Title>
+            <DraftsButton color="third" padding="4px 16px" fontSize={12} fontWeight="bold">
+              drafts
+              <Badge>
+                0
+              </Badge>
+            </DraftsButton>
+          </TitleContainer>
+          <CustomDivider />
+          <SubredditsMenu
+            setCommunityToPostIn={setCommunityToPostIn}
+            setOwnerType={setOwnerType}
+            subredditIcon={subredditIcon}
+            subredditName={subredditName}
+            ownerType={ownerType}
+            communityName={communityName}
+            setCommunityName={setCommunityName}
+            setFlair={setFlair}
+          />
+          <PostFormContainer>
+            <FieldsContainer>
+              <Box
+                position="relative"
+                display="flex"
+                flexDirection="column"
+                marginBottom={2}
+              >
+                <PostTitle
+                  type="text"
+                  placeholder="Title"
+                  value={title}
+                  onChange={handleTitleChange}
+                  onKeyDown={handleEnter}
+                />
+                <WordCounter>
+                  {title?.length}
+                  /300
+                </WordCounter>
+              </Box>
+              <SharedPost sharedFrom={parentPost} />
+            </FieldsContainer>
+            <PostTags
+              spoiler={spoiler}
+              hanldeSpoiler={hanldeSpoiler}
+              nswf={nswf}
+              hanldeNsfw={hanldeNsfw}
+              setFlair={setFlair}
+              subreddit={communityName?.substring(2)}
+              flair={flair}
+              communityName={communityName}
+            />
+            <Divider />
+            <PostSubmission
+              handleSaveDraft={handleSaveDraft}
+              handlePost={handlePost}
+              readyToPost={communityToPostIn != null && title}
+              handleSendReplies={handleSendReplies}
+              sendReplies={sendReplies}
+            />
+          </PostFormContainer>
+        </FormContainer>
+      ) : <div>error in get the parent post</div>
+  );
+}
+
+export default CreatePostForm;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_SharePostForm_SubredditsMenu_SubredditsMenu.jsx.html b/docs/components_CreatePost_CreatePostContainer_SharePostForm_SubredditsMenu_SubredditsMenu.jsx.html new file mode 100644 index 00000000..af998168 --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_SharePostForm_SubredditsMenu_SubredditsMenu.jsx.html @@ -0,0 +1,268 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/SharePostForm/SubredditsMenu/SubredditsMenu.jsx + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/SharePostForm/SubredditsMenu/SubredditsMenu.jsx

+ + + + + + +
+
+
import {
+  Box,
+  ClickAwayListener,
+  Divider, ListItem,
+} from '@mui/material';
+import { useState, useEffect } from 'react';
+import { useCookies } from 'react-cookie';
+import { useCommunitiesInCreatePostContext } from '../../../../../contexts/CommunitiesInCreatePostContext';
+import iMatcher from '../../../../../utils/iMatcher';
+import numberWithCommas from '../../../../../utils/numberWithCommas';
+import RedditButton from '../../../../RedditButton/RedditButton';
+import {
+  AvatarContainer, CommunityCategory, CustomList, DashedCircle, DropIcon, MenuContainer, MenuOuterContainer, SubredditsContainer, SubredditSearchField, CustomAvatar, CommunityName, CommunityAvatar, Members, CommunityContainer, SearchIcon, NoCommunitiesFound, ChosenCommunityIcon, ClickAwayContainer,
+} from './styles';
+
+/**
+ * This component contains the menu of subreddit that the use can post in
+ *
+ * @component SubredditsMenu
+ * @property {function} setCommunityToPostIn -Hanlding post owner (ID).
+ * @property {function} setOwnerType -Hanlding post owner type (subreddit or user).
+ * @property {string} subredditIcon -Subreddit icon.
+ * @property {string} subredditName -Subreddit name.
+ * @property {string} ownerType -to know if the type of the owner is User or Subreddit
+ * @returns {React.Component} Container of subreddit menu
+ */
+
+function SubredditsMenu(props) {
+  // props
+  const {
+    setCommunityToPostIn, setOwnerType, subredditIcon, subredditName, ownerType, communityName, setCommunityName, setFlair,
+  } = props;
+
+  // contexts
+  const { communities } = useCommunitiesInCreatePostContext();
+
+  // states
+  const [open, setOpen] = useState(false);
+  const [searching, setSearching] = useState(false);
+  const [chosenCommunityIcon, setChosenCommunityIcon] = useState(subredditIcon);
+  const [showIcon, setShowIcon] = useState(!!subredditName);
+  // console.log('show icon', showIcon);
+  // console.log(chosenCommunityIcon);
+
+  useEffect(() => {
+    setChosenCommunityIcon(subredditIcon);
+    setCommunityName(subredditName && `r/${subredditName}`);
+  }, [subredditIcon, subredditName]);
+
+  // cookies
+  const [cookies] = useCookies(['redditUser']);
+
+  // handlers
+  const handleClickOnChoose = () => {
+    setOpen(true);
+    setSearching(true);
+    setChosenCommunityIcon(null);
+    setCommunityToPostIn(null);
+    setFlair(null);
+  };
+  const handleClickAway = () => {
+    setOpen(false);
+    setSearching(false);
+    setShowIcon(true);
+  };
+  const handleDrop = () => {
+    if (open) {
+      setSearching(true);
+      setOpen(false);
+    } else {
+      setOpen(true);
+      setSearching(true);
+    }
+  };
+  const chooseCommunity = (communityId, communityName, icon, ownerType) => {
+    setCommunityToPostIn(communityId);
+    setOwnerType(ownerType);
+    setCommunityName(communityName);
+    setOpen(false);
+    setChosenCommunityIcon(icon);
+  };
+  const handleCommunityNameChange = (e) => {
+    setCommunityName(e.target.value);
+    setChosenCommunityIcon(null);
+  };
+  const handleFilter = (community) => iMatcher(`r/${community.subredditName}`, communityName);
+  // console.log(communityName);
+
+  // variables
+  const filteredArray = communities?.filter(handleFilter);
+  const filteredCommunities = filteredArray?.length === 0 ? null : filteredArray;
+  const username = cookies.redditUser?.userName;
+  const profileMatching = iMatcher(`u/${username}`, communityName);
+  const userIcon = cookies.redditUser?.profilePicture;
+
+  return (
+    <MenuOuterContainer>
+      <ClickAwayListener onClickAway={handleClickAway}>
+        <ClickAwayContainer>
+          <MenuContainer>
+            {searching ? <SearchIcon />
+              : (showIcon && chosenCommunityIcon
+                ? (
+                  <ChosenCommunityIcon
+                    src={chosenCommunityIcon}
+                    ownerType={ownerType}
+                  >
+                    {ownerType === 'Subreddit' ? 'r/' : (ownerType === 'User' ? 'u/' : '')}
+                  </ChosenCommunityIcon>
+                ) : <DashedCircle />)}
+            <SubredditSearchField
+              type="text"
+              placeholder={searching ? 'Search communities' : 'Choose a community'}
+              onClick={handleClickOnChoose}
+              value={communityName}
+              onChange={handleCommunityNameChange}
+            />
+            <DropIcon onClick={handleDrop} />
+          </MenuContainer>
+          {open
+          && searching
+          && (
+          <SubredditsContainer>
+            { profileMatching
+            && (
+            <>
+              <CommunityCategory padding="16px 16px 4px">
+                your profile
+              </CommunityCategory>
+              <CustomList>
+                <ListItem
+                  sx={{ cursor: 'pointer' }}
+                  onClick={() => chooseCommunity(0, `u/${username}`, userIcon, 'User')}
+                >
+                  <AvatarContainer>
+                    <CustomAvatar
+                      src={userIcon}
+                      alt="avatar"
+                      variant="square"
+                    >
+                      u/
+                    </CustomAvatar>
+                  </AvatarContainer>
+                  <CommunityContainer>
+                    <CommunityName>
+                      u/
+                      {username}
+                    </CommunityName>
+                  </CommunityContainer>
+                </ListItem>
+              </CustomList>
+              {(profileMatching && filteredCommunities) && <Divider />}
+            </>
+            )}
+            {!filteredCommunities && !profileMatching && (
+            <NoCommunitiesFound>
+              No communities found
+            </NoCommunitiesFound>
+            )}
+            {(!profileMatching || filteredCommunities) && (
+            <Box
+              display="flex"
+              justifyContent="space-between"
+              padding="8px 8px 3px 16px"
+              alignItems="center"
+            >
+              <CommunityCategory>
+                your communities
+              </CommunityCategory>
+              <RedditButton
+                padding="2px 8px"
+                fontSize={12}
+                fontWeight={700}
+              >
+                create new
+              </RedditButton>
+            </Box>
+            )}
+
+            <CustomList>
+              {(filteredCommunities || (profileMatching ? [] : communities))?.map((community) => {
+                const {
+                  id, subredditName, membersCount, icon,
+                } = community;
+                return (
+                  <ListItem
+                    key={id}
+                    sx={{ cursor: 'pointer' }}
+                    onClick={() => chooseCommunity(id, `r/${subredditName}`, icon, 'Subreddit')}
+                  >
+                    <CommunityAvatar src={icon}>
+                      r/
+                    </CommunityAvatar>
+                    <CommunityContainer>
+                      <CommunityName>
+                        r/
+                        {subredditName}
+                      </CommunityName>
+                      <Members>
+                        {numberWithCommas(membersCount)}
+                        {' '}
+                        members
+                      </Members>
+                    </CommunityContainer>
+                  </ListItem>
+                );
+              })}
+            </CustomList>
+            <Divider />
+          </SubredditsContainer>
+          )}
+        </ClickAwayContainer>
+      </ClickAwayListener>
+    </MenuOuterContainer>
+  );
+}
+export default SubredditsMenu;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_SharePostForm_currentSubredditServer.js.html b/docs/components_CreatePost_CreatePostContainer_SharePostForm_currentSubredditServer.js.html new file mode 100644 index 00000000..db0406bf --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_SharePostForm_currentSubredditServer.js.html @@ -0,0 +1,72 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/SharePostForm/currentSubredditServer.js + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/SharePostForm/currentSubredditServer.js

+ + + + + + +
+
+
/**
+ * This function works as a server create post page
+ *
+ * @function createPostServerforSubreddit
+ */
+
+import getSubredditAllData from '../../../SubReddit/SubrridetDataServer';
+
+const currentSubredditServer = (subredditName) => {
+  if (!subredditName) {
+    return [null, null, ''];
+  }
+  const [data] = getSubredditAllData(subredditName);
+  console.log(data);
+  const subredditId = data?._id;
+  const subredditIcon = data?.icon;
+  console.log('server', subredditId, subredditIcon, subredditName);
+  return [subredditId, subredditIcon, 'Subreddit'];
+};
+
+export default currentSubredditServer;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_SharePostForm_sharePostServer.js.html b/docs/components_CreatePost_CreatePostContainer_SharePostForm_sharePostServer.js.html new file mode 100644 index 00000000..07389030 --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_SharePostForm_sharePostServer.js.html @@ -0,0 +1,92 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/SharePostForm/sharePostServer.js + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/SharePostForm/sharePostServer.js

+ + + + + + +
+
+
import axios from '../../../../services/instance';
+import { redirectLogin } from '../../../../utils/Redirect';
+/**
+ * This function works as a server for submitting post
+ *
+ * @function submitPostServer
+ * @param {Object} post - post to be posted
+ */
+
+// eslint-disable-next-line no-unused-vars
+const sharePostServer = (post, navigate) => {
+  console.log(JSON.stringify(post));
+  console.log('kiro', post);
+  axios.post('/posts', JSON.stringify(post)).then((response) => {
+    console.log(response.data);
+    console.log(response.status);
+    console.log('env variable', process.env.REACT_APP_ENV);
+    if (response.status !== 201) {
+      if (response.status === 401) {
+        redirectLogin();
+      }
+      const { message } = response.data;
+      console.log(message);
+    } else {
+      const post = response?.data?.data;
+      console.log('response after create post', post);
+      console.log('post from response', post);
+      const postId = post?._id;
+      console.log('post from response', postId);
+      alert('posted successfully');
+      navigate('/');
+    }
+  }).catch((e) => {
+    console.log(e.response);
+    console.log(e.response.status);
+    console.log(e.response.message);
+    alert('somethig went wrong');
+  });
+};
+
+export default sharePostServer;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_CreatePost_CreatePostContainer_createPostServer.js.html b/docs/components_CreatePost_CreatePostContainer_createPostServer.js.html new file mode 100644 index 00000000..0193056c --- /dev/null +++ b/docs/components_CreatePost_CreatePostContainer_createPostServer.js.html @@ -0,0 +1,77 @@ + + + + + JSDoc: Source: components/CreatePost/CreatePostContainer/createPostServer.js + + + + + + + + + + +
+ +

Source: components/CreatePost/CreatePostContainer/createPostServer.js

+ + + + + + +
+
+
import { redirectLogin } from '../../../utils/Redirect';
+import useFetch from '../../../hooks/useFetch';
+
+/**
+ * This function works as a server create post page
+ *
+ * @function createPostServer
+ */
+
+const createPostServer = () => {
+  const communitiesUrl = '/subreddits/mine/subscriber';
+  const [data, communitiesError, statusCode] = useFetch(communitiesUrl);
+  const communities = data?.data.map((community) => ({
+    ...community, subredditName: community.fixedName, id: community._id,
+  }));
+  // console.log('communities', communities);
+  // console.log(statusCode);
+  if (statusCode === 401) {
+    redirectLogin();
+  }
+
+  console.log(statusCode);
+  return [communities, communitiesError];
+};
+
+export default createPostServer;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Explore_CommunitiesContainer_CommunitiesContainer.jsx.html b/docs/components_Explore_CommunitiesContainer_CommunitiesContainer.jsx.html new file mode 100644 index 00000000..4c2b0708 --- /dev/null +++ b/docs/components_Explore_CommunitiesContainer_CommunitiesContainer.jsx.html @@ -0,0 +1,98 @@ + + + + + JSDoc: Source: components/Explore/CommunitiesContainer/CommunitiesContainer.jsx + + + + + + + + + + +
+ +

Source: components/Explore/CommunitiesContainer/CommunitiesContainer.jsx

+ + + + + + +
+
+
import { useEffect } from 'react';
+import { useHeaderSubtitleContext } from '../../../contexts/HeaderSubtitleContext';
+import CommunitiesHeader from '../CommunitiesHeader/CommunitiesHeader';
+import Community from '../Community/Community';
+import { StyledCommunitiesContainer } from './styles';
+import { exploreCommunities } from './CommunitiesTabServer';
+
+/**
+ * communities and their header
+ * @component
+ * @property {string} title title of the communities
+ * @return {React.Component} - communities and their header
+ */
+
+function CommunitiesContainer(props) {
+  const { title } = props;
+  const [communities] = exploreCommunities(title);
+  const { setHeaderSubtitle } = useHeaderSubtitleContext();
+  useEffect(() => {
+    setHeaderSubtitle(communities?.type);
+    console.log('fady', communities?.type);
+  }, [communities]);
+  return (
+    <StyledCommunitiesContainer>
+      <CommunitiesHeader explore={title} />
+      {
+      communities?.data?.map((commuity) => {
+        console.log(commuity);
+        const {
+          _id, name, picture, membersCount, description,
+        } = commuity;
+        console.log(_id);
+        return (
+          <Community
+            communityName={name}
+            communityPicture={picture}
+            numOfMembers={membersCount}
+            description={description}
+          />
+        );
+      })
+    }
+    </StyledCommunitiesContainer>
+  );
+}
+
+export default CommunitiesContainer;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Explore_CommunitiesContainer_CommunitiesTabServer.js.html b/docs/components_Explore_CommunitiesContainer_CommunitiesTabServer.js.html new file mode 100644 index 00000000..b0b00bfd --- /dev/null +++ b/docs/components_Explore_CommunitiesContainer_CommunitiesTabServer.js.html @@ -0,0 +1,81 @@ + + + + + JSDoc: Source: components/Explore/CommunitiesContainer/CommunitiesTabServer.js + + + + + + + + + + +
+ +

Source: components/Explore/CommunitiesContainer/CommunitiesTabServer.js

+ + + + + + +
+
+
import { useState, useEffect } from 'react';
+import axios from '../../../services/instance';
+
+/**
+*
+* Function to perfom api request and fetch communities
+* @param {string} name - title of explore page
+* @returns {Array} array of communities
+*/
+
+export const exploreCommunities = (name) => {
+  const [data, setData] = useState([]);
+
+  const api = `/t/${name}/`;
+  useEffect(() => {
+    axios.get(api) // fetch api
+      .then((actualData) => {
+        console.log(actualData.data);
+        setData(actualData.data);
+      })
+      .catch((error) => {
+        if (error.response.status === 401) {
+          window.location.href = './login';
+        }
+
+        console.log(error);
+      });
+  }, [api]);
+  return [data];
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Explore_CommunitiesHeader_CommunitiesHeader.jsx.html b/docs/components_Explore_CommunitiesHeader_CommunitiesHeader.jsx.html new file mode 100644 index 00000000..95c2cb38 --- /dev/null +++ b/docs/components_Explore_CommunitiesHeader_CommunitiesHeader.jsx.html @@ -0,0 +1,75 @@ + + + + + JSDoc: Source: components/Explore/CommunitiesHeader/CommunitiesHeader.jsx + + + + + + + + + + +
+ +

Source: components/Explore/CommunitiesHeader/CommunitiesHeader.jsx

+ + + + + + +
+
+
import { Typography } from '@mui/material';
+import { StyledHeader } from './styles';
+
+/**
+ * header of the communities
+ * @component
+ * @property {string} explore the explore page header
+ * @return {React.Component} - header of the communities
+ */
+
+function CommunitiesHeader(props) {
+  const { explore } = props;
+  return (
+    <StyledHeader>
+      <Typography>
+        Communities related to
+        {' '}
+        {explore}
+      </Typography>
+    </StyledHeader>
+  );
+}
+
+export default CommunitiesHeader;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Explore_CommunitiesTab_CommunitiesTab.jsx.html b/docs/components_Explore_CommunitiesTab_CommunitiesTab.jsx.html new file mode 100644 index 00000000..2b079b2d --- /dev/null +++ b/docs/components_Explore_CommunitiesTab_CommunitiesTab.jsx.html @@ -0,0 +1,80 @@ + + + + + JSDoc: Source: components/Explore/CommunitiesTab/CommunitiesTab.jsx + + + + + + + + + + +
+ +

Source: components/Explore/CommunitiesTab/CommunitiesTab.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import BackHomeBottun from '../../BackHomeBottun/BackHome';
+import CommunitiesContainer from '../CommunitiesContainer/CommunitiesContainer';
+import SimilarTopics from '../SimilarTopics/SimilarTopics';
+import { CommunitiesTabContainer } from './styles';
+
+/**
+ * the whole page of communities
+ * @component
+ * @property {string} title the title of the communities section
+ * @return {React.Component} - communities page
+ */
+
+function CommunitiesTab(props) {
+  const { title } = props;
+  return (
+    <CommunitiesTabContainer>
+      <CommunitiesContainer
+        title={title}
+      />
+      <Box>
+        <SimilarTopics />
+        <BackHomeBottun />
+      </Box>
+    </CommunitiesTabContainer>
+  );
+}
+
+export default CommunitiesTab;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Explore_Community_Community.jsx.html b/docs/components_Explore_Community_Community.jsx.html new file mode 100644 index 00000000..1c3abded --- /dev/null +++ b/docs/components_Explore_Community_Community.jsx.html @@ -0,0 +1,116 @@ + + + + + JSDoc: Source: components/Explore/Community/Community.jsx + + + + + + + + + + +
+ +

Source: components/Explore/Community/Community.jsx

+ + + + + + +
+
+
import { Avatar, Typography, Box } from '@mui/material';
+import {
+  StyledCommunityContainer, StyledCommunity, StyledDiscription, VisitButton,
+} from './styles';
+import JoinButton from '../../JoinButton/JoinButton';
+
+/**
+ * community instance
+ * @component
+ * @property {string} communityName the name of the community
+ * @property {string} communityPicture the link of the community image
+ * @property {string} numOfMembers number of members of the community
+ * @property {string} description discription of the community
+ * @return {React.Component} - community component of explore page
+ */
+
+function Community(props) {
+  const {
+    communityName, communityPicture, numOfMembers, description,
+  } = props;
+  return (
+    <StyledCommunityContainer>
+      <StyledCommunity>
+        <Avatar sx={{ marginRight: '12px' }} src={communityPicture} />
+        <StyledDiscription>
+          <Typography
+            color="#1C1C1C"
+            fontSize="12px"
+            fontWeight={600}
+            fontFamily="Sans-Serif"
+          >
+            r/
+            {communityName}
+          </Typography>
+          <Typography
+            color="#7C7C7C"
+            fontSize="12px"
+            fontFamily="Sans-Serif"
+          >
+            {numOfMembers}
+            members
+          </Typography>
+          <Typography
+            color="#7C7C7C"
+            fontSize="12px"
+            fontFamily="Sans-Serif"
+          >
+            {description}
+          </Typography>
+          <VisitButton
+            disableRipple
+            disableFocusRipple
+          >
+            visit
+          </VisitButton>
+        </StyledDiscription>
+        <Box display="flex" justifyContent="flex-end" flexGrow={1} alignItems="flex-start">
+          <JoinButton subreddit={communityName} />
+        </Box>
+      </StyledCommunity>
+    </StyledCommunityContainer>
+  );
+}
+
+export default Community;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Explore_ExploreHeader_ExploreHeader.jsx.html b/docs/components_Explore_ExploreHeader_ExploreHeader.jsx.html new file mode 100644 index 00000000..1d2b052c --- /dev/null +++ b/docs/components_Explore_ExploreHeader_ExploreHeader.jsx.html @@ -0,0 +1,90 @@ + + + + + JSDoc: Source: components/Explore/ExploreHeader/ExploreHeader.jsx + + + + + + + + + + +
+ +

Source: components/Explore/ExploreHeader/ExploreHeader.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import { Typography, Box } from '@mui/material';
+import { HeaderContainer, StyledLink } from './styles';
+import NavButtons from '../NavButtons/NavButtons';
+import { useHeaderSubtitleContext } from '../../../contexts/HeaderSubtitleContext';
+
+/**
+ * explore page header
+ * @component
+ * @property {string} headerSubtitle the header title of the explore page
+ * @return {React.Component} - explore page header component
+ */
+
+function ExploreHeader(props) {
+  const {
+    headerSubtitle,
+  } = useHeaderSubtitleContext();
+  const { title } = props;
+  return (
+    <HeaderContainer>
+      <Box sx={{ padding: '16px 0px' }}>
+        <Typography
+          fontFamily="sans-serif"
+          fontSize="22px"
+          color="#1A1A1B"
+          fontWeight={600}
+        >
+          {title}
+        </Typography>
+        <StyledLink>
+          {headerSubtitle}
+        </StyledLink>
+      </Box>
+      <NavButtons title={title} />
+    </HeaderContainer>
+  );
+}
+
+export default ExploreHeader;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Explore_ExploreMainPage_ExploreMainPage.jsx.html b/docs/components_Explore_ExploreMainPage_ExploreMainPage.jsx.html new file mode 100644 index 00000000..04b8fd46 --- /dev/null +++ b/docs/components_Explore_ExploreMainPage_ExploreMainPage.jsx.html @@ -0,0 +1,74 @@ + + + + + JSDoc: Source: components/Explore/ExploreMainPage/ExploreMainPage.jsx + + + + + + + + + + +
+ +

Source: components/Explore/ExploreMainPage/ExploreMainPage.jsx

+ + + + + + +
+
+
import HeaderSubtitleContextProvider from '../../../contexts/HeaderSubtitleContext';
+import { ExpMainPage } from './styles';
+import ExploreHeader from '../ExploreHeader/ExploreHeader';
+
+/**
+ * the explore main page
+ * @component
+ * @property {string} title the title of the explore main page
+ * @return {React.Component} - the explore main page
+ */
+
+function ExploreMainPage(props) {
+  const { title } = props;
+  return (
+    <HeaderSubtitleContextProvider>
+      <ExpMainPage>
+        <ExploreHeader title={title} />
+      </ExpMainPage>
+    </HeaderSubtitleContextProvider>
+  );
+}
+
+export default ExploreMainPage;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Explore_NavButtons_NavButtons.jsx.html b/docs/components_Explore_NavButtons_NavButtons.jsx.html new file mode 100644 index 00000000..6857d66b --- /dev/null +++ b/docs/components_Explore_NavButtons_NavButtons.jsx.html @@ -0,0 +1,99 @@ + + + + + JSDoc: Source: components/Explore/NavButtons/NavButtons.jsx + + + + + + + + + + +
+ +

Source: components/Explore/NavButtons/NavButtons.jsx

+ + + + + + +
+
+
import * as React from 'react';
+import Box from '@mui/material/Box';
+import Tab from '@mui/material/Tab';
+import TabContext from '@mui/lab/TabContext';
+import TabPanel from '@mui/lab/TabPanel';
+import { StyledTabs } from './styles';
+import CommunitiesTab from '../CommunitiesTab/CommunitiesTab';
+
+/**
+ * navigation button for explore page between communities and posts
+ * @component
+ * @property {string} title the title of the communities
+ * @return {React.Component} - navigation buttons component
+ */
+
+export default function NavButtons(props) {
+  const { title } = props;
+  const [value, setValue] = React.useState('1');
+
+  const handleChange = (event, newValue) => {
+    setValue(newValue);
+  };
+
+  return (
+    <Box sx={{ width: '100%', typography: 'body1' }}>
+      <TabContext value={value}>
+        <StyledTabs
+          onChange={handleChange}
+        >
+          <Tab
+            disableRipple
+            label="Posts"
+            value="1"
+          />
+          <Tab
+            disableRipple
+            label="Communities"
+            value="2"
+          />
+        </StyledTabs>
+        <TabPanel value="1">Posts</TabPanel>
+        <TabPanel value="2" sx={{ width: '100%', padding: '20px 0px 0px 0px', display: 'flex' }}>
+          <CommunitiesTab title={title} />
+        </TabPanel>
+      </TabContext>
+    </Box>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Explore_SimilarTopics_SimilarTopics.jsx.html b/docs/components_Explore_SimilarTopics_SimilarTopics.jsx.html new file mode 100644 index 00000000..3e11b0cb --- /dev/null +++ b/docs/components_Explore_SimilarTopics_SimilarTopics.jsx.html @@ -0,0 +1,87 @@ + + + + + JSDoc: Source: components/Explore/SimilarTopics/SimilarTopics.jsx + + + + + + + + + + +
+ +

Source: components/Explore/SimilarTopics/SimilarTopics.jsx

+ + + + + + +
+
+
import SearchIcon from '@mui/icons-material/Search';
+import { Typography } from '@mui/material';
+import {
+  SimilarTopicsContainer, StyledLink, StyledTopic, StyledTopics,
+} from './styles';
+
+const arr = ['link1', 'link2', 'Meta', 'link'];
+
+/**
+ * similar topics of the explore page
+ * @component
+ * @return {React.Component} - similar topics component
+ */
+
+function SimilarTopics() {
+  return (
+    <SimilarTopicsContainer>
+      <StyledTopics>
+        <Typography fontSize="10px" color="#7C7C7C" fontWeight="bold" marginBottom="10px">
+          SIMILAR TOPICS
+        </Typography>
+        {
+          arr.map((item) => (
+            <StyledTopic>
+              <SearchIcon fontSize="small" />
+              <StyledLink href="/" underline="hover">
+                {item}
+              </StyledLink>
+            </StyledTopic>
+          ))
+        }
+      </StyledTopics>
+    </SimilarTopicsContainer>
+  );
+}
+export default SimilarTopics;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_Communities_Communities.jsx.html b/docs/components_HomePage_HomePageContainer_Communities_Communities.jsx.html new file mode 100644 index 00000000..01737f91 --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_Communities_Communities.jsx.html @@ -0,0 +1,129 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/Communities/Communities.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/Communities/Communities.jsx

+ + + + + + +
+
+
import { Link } from 'react-router-dom';
+import RedditButton from '../../../RedditButton/RedditButton';
+import CommunityList from './CommunityList/CommunityList';
+import {
+  CategoriesBox,
+  CommunitiesContainer, CommunitiesTypeButton, Layer, Title, ViewAllButtonBox, CustomLink,
+} from './styles';
+/**
+ * This component is upper section of home page sidebar
+ *
+ * @component Communities
+ * @property {object} communities -Object contains the title of the communities and list of them
+ * @returns {React.Component} Communities
+ */
+
+function Communities(props) {
+  // props
+  const { communities } = props;
+  const communitiesList = communities;
+
+  const communitiesTitle = 'communities near you';
+
+  return (
+    <CommunitiesContainer data-testid="Communities">
+      <Title>
+        <Layer>
+          <Link
+            to="/subreddits/leaderboard/"
+            data-testid="communities title"
+          >
+            {communitiesTitle}
+          </Link>
+        </Layer>
+      </Title>
+      <CommunityList communitiesList={communitiesList} />
+      <ViewAllButtonBox>
+        <CustomLink
+          to="/subreddits/leaderboard/aww/"
+          style={{ width: '100%' }}
+        >
+          <RedditButton
+            variant="contained"
+            padding="4px"
+            fontSize={15}
+            fontWeight="bold"
+            sx={{ width: '100%' }}
+          >
+            view all
+          </RedditButton>
+        </CustomLink>
+      </ViewAllButtonBox>
+      <CategoriesBox>
+        <CustomLink to="/subreddits/leaderboard/">
+          <CommunitiesTypeButton>
+            top
+          </CommunitiesTypeButton>
+        </CustomLink>
+        <CustomLink to="/subreddits/leaderboard/news/">
+          <CommunitiesTypeButton>
+            news
+          </CommunitiesTypeButton>
+        </CustomLink>
+        <CustomLink to="/subreddits/leaderboard/aww/">
+          <CommunitiesTypeButton>
+            aww
+          </CommunitiesTypeButton>
+        </CustomLink>
+        <CustomLink to="/subreddits/leaderboard/sports/">
+          <CommunitiesTypeButton>
+            sports
+          </CommunitiesTypeButton>
+        </CustomLink>
+      </CategoriesBox>
+    </CommunitiesContainer>
+  );
+}
+
+export default Communities;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_Communities_CommunityList_CommunityItem_CommunityItem.jsx.html b/docs/components_HomePage_HomePageContainer_Communities_CommunityList_CommunityItem_CommunityItem.jsx.html new file mode 100644 index 00000000..4300d8c4 --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_Communities_CommunityList_CommunityItem_CommunityItem.jsx.html @@ -0,0 +1,118 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/Communities/CommunityList/CommunityItem/CommunityItem.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/Communities/CommunityList/CommunityItem/CommunityItem.jsx

+ + + + + + +
+
+
import {
+  Box,
+} from '@mui/material';
+import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
+import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
+import { useNavigate } from 'react-router-dom';
+import {
+  CommunityName, CommunityImage, CommunityIndex, CommunityListItem,
+} from './styles';
+import JoinButton from '../../../../../JoinButton/JoinButton';
+/**
+ * This component represents the community in upper section of home page sidebar.
+ *
+ * @component CommunityItem
+ * @property {number} index -Community index.
+ * @property {string} icon -Community icon.
+ * @property {string} subredditName -Community name.
+ * @property {boolean} status -Community status.
+ * @property {boolean} isJoined -Check whether the logged in user is joined that community or not.
+ * @returns {React.Component} Communities
+ */
+
+function CommunityItem(props) {
+  const {
+    index, icon, subredditName, status, isJoined,
+  } = props;
+  const navigate = useNavigate();
+  const handleClick = () => {
+    console.log(`/r/${subredditName}`);
+    navigate(`/r/${subredditName}`);
+  };
+
+  return (
+    <CommunityListItem
+      data-testid="Community Item"
+      onClick={handleClick}
+    >
+      <CommunityIndex data-testid="index">
+        {index}
+      </CommunityIndex>
+      {status ? (
+        <KeyboardArrowUpIcon
+          data-testid="icon up"
+          sx={{ color: '#46d160' }}
+        />
+      ) : (
+        <KeyboardArrowDownIcon
+          data-testid="icon down"
+          sx={{ color: '#ea0027' }}
+        />
+      )}
+      <CommunityImage
+        src={icon}
+        data-testid="image"
+      />
+      <CommunityName data-testid="name" variant="caption">
+        r/
+        {subredditName}
+      </CommunityName>
+      <Box flexGrow={1} display="flex" justifyContent="flex-end">
+        <JoinButton subreddit={subredditName} isJoined={isJoined} />
+      </Box>
+    </CommunityListItem>
+  );
+}
+
+export default CommunityItem;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_Communities_CommunityList_CommunityList.jsx.html b/docs/components_HomePage_HomePageContainer_Communities_CommunityList_CommunityList.jsx.html new file mode 100644 index 00000000..25a07657 --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_Communities_CommunityList_CommunityList.jsx.html @@ -0,0 +1,89 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/Communities/CommunityList/CommunityList.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/Communities/CommunityList/CommunityList.jsx

+ + + + + + +
+
+
import {
+  List, Divider,
+} from '@mui/material';
+import CommunityItem from './CommunityItem/CommunityItem';
+/**
+ * This component represents the list of communities on home page sidebar.
+ *
+ * @component CommunityList
+ * @property {Array<community>} communities -The list of communities.
+ * @returns {React.Component} Communities
+ */
+function CommunityList(props) {
+  const { communitiesList } = props;
+  return (
+
+    <List sx={{ p: 0 }} data-testid="community list">
+      {communitiesList.map((item, index) => {
+        const {
+          id, fixedName, icon, status, isJoined,
+        } = item;
+        return (
+          <div key={id}>
+            <CommunityItem
+              index={index + 1}
+              subredditName={fixedName}
+              icon={icon}
+              status={status}
+              isJoined={isJoined}
+            />
+            {(index < communitiesList.length - 1) && <Divider />}
+          </div>
+        );
+      })}
+    </List>
+  );
+}
+
+export default CommunityList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_CreatePostInHome_CreatePostInHome.jsx.html b/docs/components_HomePage_HomePageContainer_CreatePostInHome_CreatePostInHome.jsx.html new file mode 100644 index 00000000..8a1c7143 --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_CreatePostInHome_CreatePostInHome.jsx.html @@ -0,0 +1,119 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/CreatePostInHome/CreatePostInHome.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/CreatePostInHome/CreatePostInHome.jsx

+ + + + + + +
+
+
import InsertPhotoOutlinedIcon from '@mui/icons-material/InsertPhotoOutlined';
+import AttachFileIcon from '@mui/icons-material/AttachFile';
+import { Link, useNavigate } from 'react-router-dom';
+import { useCookies } from 'react-cookie';
+import {
+  AvatarContainer, CreatePostContainer, CustomIconButton, PostTitle, CustomAvatar, CustomLink,
+} from './styles';
+import { usePostTypeContext } from '../../../../contexts/PostTypeContext';
+/**
+ * This component is the link between home page and create post page
+ * @component CreatePostInHome
+ *
+ * @property {number} subredditName - creat post from a spacific subreddit or not
+ *
+ * @returns {React.Component} User avatar
+ * @returns {React.Component} Inputs redirect user to create post page
+ */
+
+function CreatePostInHome(props) {
+  const { subredditName } = props;
+  const [cookies] = useCookies(['redditUser']);
+  const navigate = useNavigate();
+  const { setInitialPostType } = usePostTypeContext();
+  /**
+   * this function to redirect user to create post page
+   */
+  const handleClick = (postType) => {
+    navigate(subredditName ? `/submit/r/${subredditName}` : '/submit');
+    setInitialPostType(postType);
+  };
+  return (
+    <CreatePostContainer>
+      <AvatarContainer>
+        <CustomLink to={`/user/${cookies.redditUser?.userName}`}>
+          <CustomAvatar
+            src={cookies.redditUser?.profilePicture}
+            alt="avatar"
+          >
+            u/
+          </CustomAvatar>
+        </CustomLink>
+      </AvatarContainer>
+      <PostTitle
+        type="text"
+        placeholder="Create Post"
+        onClick={() => handleClick(0)}
+      />
+      <Link
+        to={subredditName ? `/submit/r/${subredditName}` : '/submit'}
+        onClick={() => handleClick(1)}
+      >
+        <CustomIconButton color="third">
+          <InsertPhotoOutlinedIcon />
+        </CustomIconButton>
+      </Link>
+      <Link
+        to={subredditName ? `/submit/r/${subredditName}` : '/submit'}
+        onClick={() => handleClick(3)}
+      >
+        <CustomIconButton color="third">
+          <AttachFileIcon sx={{ transform: 'rotate(45deg)' }} />
+        </CustomIconButton>
+      </Link>
+    </CreatePostContainer>
+  );
+}
+
+export default CreatePostInHome;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_HomePageContainer.jsx.html b/docs/components_HomePage_HomePageContainer_HomePageContainer.jsx.html new file mode 100644 index 00000000..09c0ecb7 --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_HomePageContainer.jsx.html @@ -0,0 +1,118 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/HomePageContainer.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/HomePageContainer.jsx

+ + + + + + +
+
+
import { useMediaQuery, useTheme } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import { useCookies } from 'react-cookie';
+
+import MainContent from '../../MainContent/MainContent';
+import { MainContainer, OuterContainer } from './styles';
+import SideBar from '../../SideBar/SideBar';
+import Communities from './Communities/Communities';
+import RedditPremium from './RedditPremium/RedditPremium';
+import PersonalReddit from './PersonalReddit/PersonalReddit';
+import HomePageFooter from './HomePageFooter/HomePageFooter';
+import PostsClassification from './PostsClassification/PostsClassification';
+import CreatePostInHome from './CreatePostInHome/CreatePostInHome';
+import BackToTop from '../../BackToTop/BackToTop';
+import PostList from './PostList/PostList';
+import homePageServer from './homePageServer';
+import cleanPage from '../../../utils/cleanPage';
+
+/**
+ * This component works as a container for all home page components
+ * and a repository the data fetched in
+ *
+ * @component HomePageContainer
+ * @returns {React.Component} Container represents the home page
+ */
+function HomePageContainer() {
+  const { postClass } = useParams();
+  // variables
+  const theme = useTheme();
+  const match = useMediaQuery(theme.breakpoints.up('md'));
+
+  // states
+  const [posts, postsError, communities, communitiesError] = homePageServer(postClass);
+
+  // Cookies
+  const [cookies] = useCookies(['redditUser']);
+
+  cleanPage();
+
+  return (
+    <OuterContainer>
+      <MainContainer>
+        <MainContent width={640}>
+          {cookies.redditUser ? <CreatePostInHome /> : null}
+          <PostsClassification />
+          {!postsError ? (posts && <PostList posts={posts} />) : 'error in fetching posts'}
+        </MainContent>
+        {match
+        && (
+        <SideBar>
+          {cookies.redditUser && (!communitiesError ? (communities && <Communities communities={communities} />) : 'error in fetching commmunities')}
+          <RedditPremium />
+          <PersonalReddit
+            title="Home"
+            paragraph="Your personal Reddit frontpage. Come here to check in with your favorite communities."
+            image="https://www.redditstatic.com/desktop2x/img/id-cards/home-banner@2x.png"
+          />
+          <HomePageFooter />
+          <BackToTop />
+        </SideBar>
+        )}
+      </MainContainer>
+    </OuterContainer>
+  );
+}
+
+export default HomePageContainer;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_HomePageFooter_HomePageFooter.jsx.html b/docs/components_HomePage_HomePageContainer_HomePageFooter_HomePageFooter.jsx.html new file mode 100644 index 00000000..38d8b616 --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_HomePageFooter_HomePageFooter.jsx.html @@ -0,0 +1,109 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/HomePageFooter/HomePageFooter.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/HomePageFooter/HomePageFooter.jsx

+ + + + + + +
+
+
import { Divider } from '@mui/material';
+import {
+  Column, Footer, Row,
+} from './styles';
+/**
+ * This component is the footer of the page
+ *
+ * @component HomePageFooter
+ * @returns {React.Component} Footer
+ */
+
+function HomePageFooter() {
+  return (
+    <Footer>
+      <Row>
+        <Column>
+          User Agreement
+        </Column>
+        <Column>
+          Content Policy
+        </Column>
+        <Column>
+          Privacy Policy
+        </Column>
+        <Column>
+          Moderator Code Of Conduct
+        </Column>
+      </Row>
+      <Divider sx={{ mb: 1 }} />
+      <Row>
+        <Column>
+          English
+        </Column>
+        <Column>
+          Franรงais
+        </Column>
+        <Column>
+          Italiano
+        </Column>
+        <Column>
+          Deutsch
+        </Column>
+        <Column>
+          Espaรฑol
+        </Column>
+        <Column>
+          Portuguรชs
+        </Column>
+      </Row>
+      <Divider sx={{ mb: 1 }} />
+      <div>
+        Reddit Inc ยฉ 2022. All rights reserved
+      </div>
+    </Footer>
+  );
+}
+
+export default HomePageFooter;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_PersonalReddit_PersonalReddit.jsx.html b/docs/components_HomePage_HomePageContainer_PersonalReddit_PersonalReddit.jsx.html new file mode 100644 index 00000000..eb948075 --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_PersonalReddit_PersonalReddit.jsx.html @@ -0,0 +1,102 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/PersonalReddit/PersonalReddit.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/PersonalReddit/PersonalReddit.jsx

+ + + + + + +
+
+
import { Divider, Typography } from '@mui/material';
+import {
+  RedditPersonal, Paragraph, RedditImage, MiddleBox, UpperImage, CustomLink,
+} from './styles';
+import RedditButton from '../../../RedditButton/RedditButton';
+import FormDialog from './PopUpSubReddit/PopUp';
+/**
+ * This component contains info about personal
+ * Reddit frontpage.
+ *
+ * @component PersonalReddit
+ * @property {string} title -Title of personal reddit
+ * @property {string} paragraph -Paragraph of personal reddit
+ * @property {string} image -Image of personal reddit
+ * @returns {React.Component}  Buttons to show info about communities
+ */
+
+function PersonalReddit(props) {
+  const { title, paragraph, image } = props;
+  return (
+    <RedditPersonal>
+      <UpperImage src={image} />
+      <MiddleBox>
+        <RedditImage src="https://www.redditstatic.com/desktop2x/img/id-cards/snoo-home@2x.png" />
+        <Typography
+          component="p"
+          sx={{
+            fontWeight: 500,
+            marginLeft: 7,
+            pb: 0.8,
+            pt: 3,
+          }}
+        >
+          {title}
+        </Typography>
+      </MiddleBox>
+      <Paragraph>
+        {paragraph}
+      </Paragraph>
+      <Divider sx={{ mt: 1.5 }} />
+      <CustomLink to="/submit">
+        <RedditButton variant="contained" padding="4px" fontSize={15} fontWeight="bold" sx={{ mt: 1.8 }}>
+          create post
+        </RedditButton>
+      </CustomLink>
+      <FormDialog />
+    </RedditPersonal>
+  );
+}
+
+export default PersonalReddit;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_PersonalReddit_PopUpSubReddit_Header_Header.jsx.html b/docs/components_HomePage_HomePageContainer_PersonalReddit_PopUpSubReddit_Header_Header.jsx.html new file mode 100644 index 00000000..e09ec09a --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_PersonalReddit_PopUpSubReddit_Header_Header.jsx.html @@ -0,0 +1,89 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/Header/Header.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/Header/Header.jsx

+ + + + + + +
+
+
import CloseIcon from '@mui/icons-material/Close';
+import { IconButton } from '@mui/material';
+import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
+import {
+  BOX, DialogTitle, Disc, Name, SecConatiner, StyledTooltip,
+} from './style';
+/**
+ *@component
+ * @param {object} props
+ * @return {React.Component} -Header for pop up form
+ */
+function Header(props) {
+  const { handleClose } = props;
+  return (
+    <>
+      {' '}
+      <BOX>
+        <DialogTitle>Create a community</DialogTitle>
+        <CloseIcon sx={{ cursor: 'pointer' }} onClick={handleClose} />
+      </BOX>
+      <SecConatiner>
+        <Name>Name</Name>
+        <Disc sx={{ height: 'fit-content', alignItems: 'center' }}>
+          Community names including capitalization cannot be changed.
+          <StyledTooltip
+            title='Names cannot have spaces (e.g., "r/bookclub" not "r/book club"), must be between 3-21 characters, and underscores ("_") are the only special characters allowed. Avoid using solely trademarked names (e.g., "r/FansOfAcme" not "r/Acme").'
+          >
+            <IconButton>
+              <ErrorOutlineIcon sx={{ transform: 'rotate(180deg)', fontSize: 'small', color: 'gray' }} />
+            </IconButton>
+          </StyledTooltip>
+        </Disc>
+      </SecConatiner>
+    </>
+
+  );
+}
+export default Header;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_PersonalReddit_PopUpSubReddit_Input_Input.jsx.html b/docs/components_HomePage_HomePageContainer_PersonalReddit_PopUpSubReddit_Input_Input.jsx.html new file mode 100644 index 00000000..5db2c598 --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_PersonalReddit_PopUpSubReddit_Input_Input.jsx.html @@ -0,0 +1,100 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/Input/Input.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/Input/Input.jsx

+ + + + + + +
+
+
import {
+  FilledInput, FormControl, InputAdornment, InputLabel,
+} from '@mui/material';
+import { Count } from './style';
+/**
+ * @component
+ * @param {object} props
+ * @return {React.Component} -input for pop up form
+ */
+function Input(props) {
+  const {
+    subRedditName, handleChange, check, count, checked, errorMassage,
+  } = props;
+  return (
+    <>
+      <FormControl fullWidth sx={{ height: 28 }}>
+        <InputLabel htmlFor="name" />
+        <FilledInput
+          sx={{
+            '&: after': { borderBottom: '2px solid #040404de', padding: 0 },
+            height: 28,
+            '& .css-1vbc0rj-MuiInputBase-input-MuiFilledInput-input': { padding: 0 },
+          }}
+          onInput={(e) => {
+          // eslint-disable-next-line radix
+            e.target.value = e.target.value.slice(0, 21);
+          }}
+          id="name"
+          data-testid="input"
+          value={subRedditName}
+          onChange={handleChange}
+          startAdornment={<InputAdornment position="start">r/</InputAdornment>}
+          maxLength={21}
+          onBlur={check}
+        />
+      </FormControl>
+      <Count
+        condition={(count === 0).toString()}
+      >
+        {count}
+        {' '}
+        Characters remaining
+      </Count>
+      <Count data-testid="warning" condition="true">{checked}</Count>
+      <Count condition="true">{errorMassage}</Count>
+    </>
+  );
+}
+export default Input;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_PersonalReddit_PopUpSubReddit_PopUp.jsx.html b/docs/components_HomePage_HomePageContainer_PersonalReddit_PopUpSubReddit_PopUp.jsx.html new file mode 100644 index 00000000..83824671 --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_PersonalReddit_PopUpSubReddit_PopUp.jsx.html @@ -0,0 +1,225 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/PopUp.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/PopUp.jsx

+ + + + + + +
+
+
import * as React from 'react';
+import {
+  Box, Checkbox, Dialog, FormControlLabel, FormGroup, Stack,
+} from '@mui/material';
+import { useEffect } from 'react';
+import {
+  Actions, Adult, AdultContent, Container, NSFWs, Warning, Btn,
+} from './style';
+import { CreatPost, CustomLink } from '../../../../SubReddit/SideBar/AboutSubReddit/style';
+import RedditButton from '../../../../RedditButton/RedditButton';
+import RadioBtn from './RadioBtn/RadioBtn';
+import Header from './Header/Header';
+import Input from './Input/Input';
+import useFetch from './PopupFetch';
+import PostData from './PopupPost';
+
+// const Form = axios.create({
+//   baseURL: 'https://60d14a9b-9245-421f-9841-d211208805b8.mock.pstmn.io',
+// });
+/**
+ * Pop up Creat Cummunity Form
+ * @component
+ * @return {React.Component} - Popup Form
+ */
+function FormDialog({ display }) {
+  const [open, setOpen] = React.useState(false);
+  const [subRedditName, setsubRedditName] = React.useState('');
+  const [count, setcount] = React.useState(21);
+  const [checked, setchecked] = React.useState('');
+  const [type, setType] = React.useState('Public');
+  const [adult, setAdult] = React.useState(false);
+  const [errorMassage, setErrorMassage] = React.useState('');
+  const [statusCode, setStatusCode] = React.useState(null);
+  const [statusCode2, setStatusCode2] = React.useState(null);
+
+  /**
+   * this function to open the popup form on click the button
+   */
+  const handleClickOpen = () => {
+    setOpen(true);
+  };
+  /**
+   * this function to close the popup form on click  cancel , x , outside the form
+   */
+  const handleClose = () => {
+    setOpen(false);
+  };/**
+   * this function to know if Subreddit Name reach max(21) or not
+    to prevent type more than 21 char in the input field and calculate number of char in input feild
+   * @param {object} event - the input field
+   */
+  const handleChange = (event) => {
+    if (event.target.value.length < 22) {
+      setsubRedditName(event.target.value);
+      setcount(21 - event.target.value.length);
+    }
+  };
+  /**
+   * this function to show message when bluring of the input feild if it is empty
+   */
+  const check = async () => {
+    console.log('#####');
+    const ele = document.getElementById('name');
+    if (ele.value.length === 0) {
+      setchecked('A community name is required');
+    } else if (ele.value.length < 4) {
+      setchecked('Community names must be between 3-21 characters');
+    } else {
+      setchecked('');
+    }
+    /**
+     * send subreddit name to check if there is another one with same name
+     */
+    // axios.get(`http://localhost:8000/subreddit/${{ subRedditName }}`, {
+    //   subredditName: subRedditName,
+    // })
+    // const [data, dataError] = await useFetch(`/subreddits/${subRedditName}`);
+    // console.log(dataError);
+    // console.log(data);
+    const { data, status } = useFetch(`/subreddits/${subRedditName}`);
+    setStatusCode(status);
+    if (data) {
+      setErrorMassage(`Sorry, r/${subRedditName} is taken. Try another.`);
+    }
+  };
+
+  useEffect(() => {
+    if (statusCode === 401 || statusCode2 === 401) {
+      window.location.pathname = 'login';
+    }
+  }, [statusCode, statusCode2]);
+
+  /**
+   * this function to click checkbox on click the text next to it
+   */
+  const check18 = () => {
+    const ele = document.getElementById('myCheck');
+    ele.click();
+  };
+  // to set the type which selected in radio button
+  const myType = (t) => {
+    setType(t);
+  };
+  /**
+   * make post action
+   * @param {object} e -sbmit button
+   */
+  const Submit = async (e) => {
+    e.preventDefault();
+    if (subRedditName !== '' && errorMassage === '' && subRedditName?.trim()?.length > 3) {
+      console.log(subRedditName, ' ', type, ' ', adult);
+      // axios.post('http://localhost:8000/subreddits/401', {
+      //   owner: user,                                               ------> from log in in ุชุฌู…ูŠุนู‡
+      //   name: subRedditName,
+      //   type,
+      //   NSFW: adult,
+      // })
+      const status = await PostData('/subreddits', subRedditName, type, adult);
+      console.log(status);
+      setStatusCode2(status);
+      // if (status === 200 || status === 204) {
+      //   window.location.pathname = `Subreddit/${subRedditName}`;
+      // }
+    }
+  };
+  return (
+    <>
+      <CustomLink sx={{ display }}>
+        <RedditButton
+          variant="outlined"
+          padding="4px"
+          fontSize={15}
+          fontWeight="bold"
+          sx={{ mt: 1.8 }}
+          onClick={handleClickOpen}
+          data-testid="btn"
+          id="popup-form-button"
+        >
+          create community
+        </RedditButton>
+      </CustomLink>
+      <Container>
+        <Dialog open={open} onClose={handleClose}>
+          <Box sx={{ p: 2 }}>
+            <Header handleClose={handleClose} />
+            <Input subRedditName={subRedditName} handleChange={handleChange} check={check} count={count} checked={checked} errorMassage={errorMassage} />
+            <RadioBtn myType={myType} />
+            <AdultContent> Adult content</AdultContent>
+            <Adult>
+              <FormGroup>
+                <FormControlLabel control={<Checkbox data-testid="my-Check-Box" id="myCheck" onClick={(ele) => { setAdult(ele.target.checked); }} />} />
+              </FormGroup>
+              <Adult onClick={check18} data-testid="cont">
+                <NSFWs>NSFW</NSFWs>
+                <Warning>18+ year old community</Warning>
+              </Adult>
+            </Adult>
+          </Box>
+          <Actions>
+            <Stack spacing={2} direction="row" sx={{ alignItems: 'center' }}>
+              <Btn data-testid="cancel-Btn" variant="outlined" onClick={handleClose}>Cancel</Btn>
+            </Stack>
+            <CustomLink>
+              <CreatPost variant="outlined" padding="4px" fontSize={15} fontWeight="bold" onClick={Submit}>
+                Create community
+              </CreatPost>
+            </CustomLink>
+          </Actions>
+        </Dialog>
+      </Container>
+    </>
+  );
+}
+export default FormDialog;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_PersonalReddit_PopUpSubReddit_RadioBtn_RadioBtn.jsx.html b/docs/components_HomePage_HomePageContainer_PersonalReddit_PopUpSubReddit_RadioBtn_RadioBtn.jsx.html new file mode 100644 index 00000000..15efc079 --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_PersonalReddit_PopUpSubReddit_RadioBtn_RadioBtn.jsx.html @@ -0,0 +1,112 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/RadioBtn/RadioBtn.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/RadioBtn/RadioBtn.jsx

+ + + + + + +
+
+
import {
+  FormControl, FormControlLabel, Radio, RadioGroup,
+} from '@mui/material';
+import PersonIcon from '@mui/icons-material/Person';
+import VisibilityIcon from '@mui/icons-material/Visibility';
+import HttpsIcon from '@mui/icons-material/Https';
+import {
+  Cont, ContUp, Disc, Name, SelectHeader,
+} from './style';
+/**
+ *@component
+ * @param {object} props
+ * @return {React.Component} -radio button in  pop up form
+ */
+function RadioBtn(props) {
+  const { myType } = props;
+  return (
+    <>
+      <SelectHeader> Community type</SelectHeader>
+      <FormControl sx={{ marginBottom: '30px' }}>
+        <RadioGroup
+          aria-labelledby="demo-radio-buttons-group-label"
+          name="radio-buttons-group"
+          id="type"
+          defaultValue="Public"
+          onChange={(e) => myType(e.target.value)}
+        >
+          <ContUp condition2="true">
+            <Cont>
+              <FormControlLabel value="Public" control={<Radio />} sx={{ margin: 0 }} />
+              <PersonIcon sx={{ color: 'gray' }} />
+              <Name sx={{ margin: 1 }}>Public</Name>
+            </Cont>
+            <Disc sx={{ pt: 0.5 }}>Anyone can view, post, and comment to this community</Disc>
+          </ContUp>
+          <ContUp>
+            <Cont>
+              <FormControlLabel value="Restricted" control={<Radio />} sx={{ margin: 0 }} />
+              <VisibilityIcon sx={{ color: 'gray' }} />
+              <Name sx={{ margin: 1 }}>Restricted</Name>
+            </Cont>
+            <Disc sx={{ pt: 0.5 }}>
+              Anyone can view this community, but only approved users can post
+            </Disc>
+          </ContUp>
+          <ContUp condition="true">
+            <Cont>
+              <FormControlLabel value="Private" control={<Radio />} sx={{ margin: 0 }} />
+              <HttpsIcon sx={{ color: 'gray' }} />
+              <Name sx={{ margin: 1 }}>Private</Name>
+            </Cont>
+            <Disc sx={{ pt: 0.5 }}>
+              Only approved users can view and submit to this community
+            </Disc>
+          </ContUp>
+        </RadioGroup>
+      </FormControl>
+    </>
+  );
+}
+export default RadioBtn;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_PostList_PostList.jsx.html b/docs/components_HomePage_HomePageContainer_PostList_PostList.jsx.html new file mode 100644 index 00000000..3e87bec6 --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_PostList_PostList.jsx.html @@ -0,0 +1,123 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/PostList/PostList.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/PostList/PostList.jsx

+ + + + + + +
+
+
import InfiniteScroll from 'react-infinite-scroll-component';
+import { useListingContext } from '../../../../contexts/ListingContext';
+import { useHiddenPostsContext } from '../../../../contexts/HiddenPostsContext';
+import Post from '../../../Post/Post';
+/**
+ * This component is the timeline (the container which contains all posts retrieved to be displayed)
+ *
+ * @component PostList
+ * @property {Array.<post>} posts -post objects fetched
+ * @returns {React.Component} List of all posts
+ */
+
+function PostList(props) {
+  const { posts, subredit } = props;
+  const { hiddenPosts } = useHiddenPostsContext();
+  console.log(subredit);
+  const { setPage } = useListingContext();
+  const fetchMoreData = () => {
+    // console.log('bazwed', page);
+    setPage((page) => page + 1);
+  };
+  console.log('el posts mn el subreddit', posts);
+  return (
+    <InfiniteScroll
+      next={fetchMoreData}
+      hasMore
+      dataLength={posts.length}
+    >
+      {posts.filter((post) => {
+        const id = post?._id;
+        return !hiddenPosts?.includes(id);
+      }).map((post, index) => {
+        const {
+          _id: id, createdAt, title, images, ownerName, ownerIcon, authorName, flairText, flairBackgroundColor, flairColor, kind, votes, commentCount, text, video, ownerType, postVoteStatus, isSaved, url, nsfw, spoiler,
+          sharedFrom,
+        } = post;
+        return (
+
+          <Post
+            postVoteStatus={postVoteStatus || 0}
+            createdAt={createdAt}
+            title={title}
+            ownerIcon={ownerIcon}
+            ownerName={ownerName}
+            authorName={authorName}
+            flairText={flairText}
+            flairBackgroundColor={flairBackgroundColor}
+            flairColor={flairColor}
+            images={images}
+            video={video}
+            kind={kind}
+            votes={votes}
+            commentCount={commentCount}
+            text={text}
+            // eslint-disable-next-line react/no-array-index-key
+            key={id + index}
+            ownerType={ownerType}
+            isSaved={isSaved}
+            postId={id}
+            url={url}
+            nsfw={nsfw}
+            spoiler={spoiler}
+            subredit={subredit}
+            sharedFrom={sharedFrom}
+          />
+        );
+      })}
+    </InfiniteScroll>
+  );
+}
+
+export default PostList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_PostsClassification_PostsClassification.jsx.html b/docs/components_HomePage_HomePageContainer_PostsClassification_PostsClassification.jsx.html new file mode 100644 index 00000000..f0bcb505 --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_PostsClassification_PostsClassification.jsx.html @@ -0,0 +1,191 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/PostsClassification/PostsClassification.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/PostsClassification/PostsClassification.jsx

+ + + + + + +
+
+
import RocketOutlinedIcon from '@mui/icons-material/RocketOutlined';
+import RocketIcon from '@mui/icons-material/Rocket';
+import LocalFireDepartmentOutlinedIcon from '@mui/icons-material/LocalFireDepartmentOutlined';
+import LocalFireDepartmentIcon from '@mui/icons-material/LocalFireDepartment';
+import NewReleasesOutlinedIcon from '@mui/icons-material/NewReleasesOutlined';
+import NewReleasesIcon from '@mui/icons-material/NewReleases';
+import UploadOutlinedIcon from '@mui/icons-material/UploadOutlined';
+import UploadIcon from '@mui/icons-material/Upload';
+import { useParams } from 'react-router-dom';
+import { useState, useEffect } from 'react';
+import { ClickAwayListener, useMediaQuery } from '@mui/material';
+import { useTheme } from '@mui/system';
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
+import {
+  CustomClassLink, PostsClassContainer, ClassButton, PostClassesList, PostClassSmButton,
+} from './styles';
+
+/**
+ * Determine which type of posts should be fetched
+ * @component PostsClassification
+ * @returns {React.Component} Tabs (each tab indicate the type of posts that will be fetched)
+ */
+
+function PostsClassification(props) {
+  const { subredditName, allOrPopular } = props;
+  const { postClass } = useParams();
+  const [activeClass, setActiveClass] = useState(null);
+  const [open, setOpen] = useState(false);
+  const theme = useTheme();
+  const matchSm = useMediaQuery(theme.breakpoints.up('sm'));
+  const postClasses = [
+    {
+      name: 'best',
+      activeIcon: <RocketIcon />,
+      nonActiveIcon: <RocketOutlinedIcon />,
+    },
+
+    {
+      name: 'hot',
+      activeIcon: <LocalFireDepartmentIcon />,
+      nonActiveIcon: <LocalFireDepartmentOutlinedIcon />,
+    },
+    {
+      name: 'new',
+      activeIcon: <NewReleasesIcon />,
+      nonActiveIcon: <NewReleasesOutlinedIcon />,
+    },
+    {
+      name: 'top',
+      activeIcon: <UploadIcon />,
+      nonActiveIcon: <UploadOutlinedIcon />,
+    },
+  ];
+
+  /**
+   * this function handles change in post class
+   */
+  const handleChangeClass = (e) => {
+    e.stopPropagation();
+    setOpen(false);
+  };
+  /**
+   * this function handles click away from posts classification post
+   */
+  const handleClickAway = () => {
+    setOpen(false);
+  };
+  useEffect(() => {
+    setActiveClass(postClass || 'best');
+    if (subredditName) {
+      setActiveClass(postClass || 'hot');
+    }
+  }, [postClass]);
+
+  /**
+   * this function set the active class of posts
+   */
+  const handleClick = (e) => {
+    if (!matchSm) {
+      e.preventDefault();
+      setOpen(true);
+    }
+  };
+  return (
+    <PostsClassContainer>
+      {postClasses.map((ele) => {
+        const { name, activeIcon, nonActiveIcon } = ele;
+
+        return (
+          !(name === 'best' && subredditName)
+            && (matchSm || activeClass === name)
+            && (
+            <CustomClassLink
+              onClick={handleClick}
+              to={(subredditName) ? `/r/${subredditName}/${name}/` : `/${(allOrPopular || '') + name}/`}
+              key={name}
+            >
+              <ClassButton
+                color={(activeClass === name ? 'primary' : 'third')}
+                active={activeClass === name}
+              >
+                {(activeClass === name && matchSm ? activeIcon : nonActiveIcon)}
+                <div>
+                  {name}
+                </div>
+                {!matchSm && <ExpandMoreIcon />}
+              </ClassButton>
+              {!matchSm && activeClass === name && open
+              && (
+                <ClickAwayListener onClickAway={handleClickAway}>
+                  <PostClassesList boxShadow={2}>
+                    {postClasses.map((innerEle) => {
+                      const { name, nonActiveIcon } = innerEle;
+                      return (
+                        <PostClassSmButton
+                          to={(subredditName) ? `/r/${subredditName}/${name}/` : `/${(allOrPopular || '') + name}/`}
+                          key={name}
+                          active={activeClass === name}
+                          onClick={handleChangeClass}
+                        >
+                          {nonActiveIcon}
+                          <div>
+                            {name}
+                          </div>
+                        </PostClassSmButton>
+                      );
+                    })}
+                  </PostClassesList>
+                </ClickAwayListener>
+              )}
+            </CustomClassLink>
+            )
+        );
+      })}
+
+    </PostsClassContainer>
+  );
+}
+
+export default PostsClassification;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_HomePage_HomePageContainer_RedditPremium_RedditPremium.jsx.html b/docs/components_HomePage_HomePageContainer_RedditPremium_RedditPremium.jsx.html new file mode 100644 index 00000000..e93cf23a --- /dev/null +++ b/docs/components_HomePage_HomePageContainer_RedditPremium_RedditPremium.jsx.html @@ -0,0 +1,90 @@ + + + + + JSDoc: Source: components/HomePage/HomePageContainer/RedditPremium/RedditPremium.jsx + + + + + + + + + + +
+ +

Source: components/HomePage/HomePageContainer/RedditPremium/RedditPremium.jsx

+ + + + + + +
+
+
import { Box } from '@mui/system';
+import SportsScoreIcon from '@mui/icons-material/SportsScore';
+import RedditButton from '../../../RedditButton/RedditButton';
+import { Header, Paragraph, PremiumReddit } from './styles';
+/**
+ * This component contains info about reddit premium.
+ *
+ * @component RedditPremium
+ * @returns {React.Component}  Information about Premium version of reddit.
+ */
+
+function RedditPremium() {
+  return (
+    <PremiumReddit>
+      <Box display="flex" mb={2}>
+        <SportsScoreIcon
+          sx={{
+            fontSize: 40,
+            mx: 1,
+          }}
+          color="secondary"
+        />
+        <Box display="flex" flexDirection="column">
+          <Header>
+            Reddit Premium
+          </Header>
+          <Paragraph>
+            The best Reddit experience, with monthly Coins
+          </Paragraph>
+        </Box>
+      </Box>
+      <RedditButton variant="contained" color="secondary" padding="4px" fontSize={15} fontWeight="bold">
+        try now
+      </RedditButton>
+    </PremiumReddit>
+  );
+}
+
+export default RedditPremium;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_JoinButton_JoinButton.jsx.html b/docs/components_JoinButton_JoinButton.jsx.html new file mode 100644 index 00000000..bbbc0486 --- /dev/null +++ b/docs/components_JoinButton_JoinButton.jsx.html @@ -0,0 +1,104 @@ + + + + + JSDoc: Source: components/JoinButton/JoinButton.jsx + + + + + + + + + + +
+ +

Source: components/JoinButton/JoinButton.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+import PostJoin from '../SubReddit/PostJoin';
+import { Button } from './styles';
+/**
+ * This component is join button
+ *
+ * @component PostHeader
+ * @property {boolean} isJoined -Check whether the user joined the subreddit or not.
+ * @returns {React.Component} Join button
+ */
+
+function JoinButton(props) {
+  const { isJoined, subreddit } = props;
+
+  const [joined, setJoined] = useState(isJoined);
+  const [hover, setHover] = useState(false);
+
+  /**
+   * this function toggles the join state of the user
+   */
+  const handleClick = (e) => {
+    e.stopPropagation();
+    PostJoin(`/subreddits/${subreddit}/subscribe`, joined ? 'unsub' : 'sub');
+    setJoined(!joined);
+  };
+
+  /**
+   * this function display leave to user if he have already joined the community while hovering
+   */
+  const handleMouseIn = () => {
+    setHover(true);
+  };
+
+  /**
+   * this function display joined to user if he have already joined the community while not hovering
+   */
+  const handleMouseOut = () => {
+    setHover(false);
+  };
+  return (
+    <Button
+      variant={(joined ? 'outlined' : 'contained')}
+      onClick={handleClick}
+      onMouseEnter={handleMouseIn}
+      onMouseLeave={handleMouseOut}
+      data-testid="join button"
+    >
+      {(joined ? (hover ? 'leave' : 'joined') : 'join')}
+    </Button>
+  );
+}
+
+export default JoinButton;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainContent_MainContent.jsx.html b/docs/components_MainContent_MainContent.jsx.html new file mode 100644 index 00000000..1508564b --- /dev/null +++ b/docs/components_MainContent_MainContent.jsx.html @@ -0,0 +1,71 @@ + + + + + JSDoc: Source: components/MainContent/MainContent.jsx + + + + + + + + + + +
+ +

Source: components/MainContent/MainContent.jsx

+ + + + + + +
+
+
import { MainContentContainer } from './styles';
+/**
+ * This component works as a container for the left half components
+ * like timeline
+ *
+ * @component MainContent
+ * @property {React.Component} children -Components which will be wrapped in main container
+ * @property {number} width -The maximum width of the main content
+ * @returns {React.Component} Container represents its children
+ */
+
+function MainContent({ children, width }) {
+  return (
+    <MainContentContainer width={width}>
+      {children}
+    </MainContentContainer>
+  );
+}
+
+export default MainContent;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_Navbar_HomeList_HomeList.jsx.html b/docs/components_MainNavBar_Navbar_HomeList_HomeList.jsx.html new file mode 100644 index 00000000..8c7a4560 --- /dev/null +++ b/docs/components_MainNavBar_Navbar_HomeList_HomeList.jsx.html @@ -0,0 +1,222 @@ + + + + + JSDoc: Source: components/MainNavBar/Navbar/HomeList/HomeList.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/Navbar/HomeList/HomeList.jsx

+ + + + + + +
+
+
/* eslint-disable react/no-array-index-key */
+import HomeIcon from '@mui/icons-material/Home';
+import ContactlessOutlinedIcon from '@mui/icons-material/ContactlessOutlined';
+import {
+  List, ListItemButton, ListItemIcon, ListItemText,
+  Collapse, ListSubheader, ClickAwayListener,
+} from '@mui/material';
+import ExpandMore from '@mui/icons-material/ExpandMore';
+import * as React from 'react';
+import OutboundOutlinedIcon from '@mui/icons-material/OutboundOutlined';
+import Avatar from '@mui/material/Avatar';
+import AddIcon from '@mui/icons-material/Add';
+import NotificationsNoneIcon from '@mui/icons-material/NotificationsNone';
+import { Link } from 'react-router-dom';
+import StyledList from './styles';
+import Reddit from '../assests/Reddit.svg';
+import FormDialog from '../../../HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/PopUp';
+
+/**
+ *  HomeList
+ * @component
+ * @returns {React.Component} left list in navbar in logged in mode
+ */
+function HomeList() {
+  const [openHomeList, setopenHomeList] = React.useState(0);
+  const handleClickHomeList = () => {
+    setopenHomeList(!openHomeList);
+  };
+  const feedsList = [
+    { icon: <HomeIcon />, label: 'home' },
+    { icon: <OutboundOutlinedIcon />, label: 'popular' },
+    { icon: <ContactlessOutlinedIcon />, label: 'all' },
+  ];
+  const othersList = [
+    { icon: <Avatar src={Reddit} />, label: 'user settings' },
+    { icon: <Avatar src={Reddit} />, label: 'messages' },
+    { icon: <AddIcon sx={{ fontSize: 30 }} />, label: 'create post' },
+    { icon: <AddIcon sx={{ fontSize: 30 }} />, label: 'create subreddit' },
+    { icon: <ContactlessOutlinedIcon />, label: 'top communities' },
+    { icon: <NotificationsNoneIcon />, label: 'notifications' },
+  ];
+  return (
+    <ClickAwayListener onClickAway={() => { setopenHomeList(false); }}>
+      <StyledList>
+        <ListItemButton onClick={handleClickHomeList}>
+          <ListItemIcon>
+            <HomeIcon />
+          </ListItemIcon>
+          <ListItemText primary="Home" sx={{ color: 'black', paddingLeft: '5px' }} />
+          <ExpandMore sx={{ color: '#757575', fontSize: 20 }} />
+        </ListItemButton>
+        <Collapse in={Boolean(openHomeList)} timeout="auto" unmountOnExit sx={{ position: 'absolute', width: '270px', left: '0px' }}>
+          <List component="div" disablePadding subheader={<ListSubheader>feeds</ListSubheader>}>
+            {feedsList.map((items, index) => (
+              (items.label === 'home') ? (
+
+                <ListItemButton key={`${index + 0}`}>
+                  <Link to="/" style={{ textDecoration: 'none', display: 'flex' }}>
+                    <ListItemIcon>
+                      {items.icon}
+                    </ListItemIcon>
+                    <ListItemText primary={items.label} />
+                  </Link>
+                </ListItemButton>
+
+              ) : (items.label === 'popular')
+                ? (
+                  <ListItemButton key={`${index + 0}`}>
+                    <Link to="/r/popular" style={{ textDecoration: 'none', display: 'flex' }}>
+                      <ListItemIcon>
+                        {items.icon}
+                      </ListItemIcon>
+                      <ListItemText primary={items.label} />
+                    </Link>
+                  </ListItemButton>
+                )
+                : (
+                  <ListItemButton key={`${index + 0}`}>
+                    <Link to="/r/all" style={{ textDecoration: 'none', display: 'flex' }}>
+                      <ListItemIcon>
+                        {items.icon}
+                      </ListItemIcon>
+                      <ListItemText primary={items.label} />
+                    </Link>
+                  </ListItemButton>
+                )
+            ))}
+          </List>
+          <List component="div" disablePadding subheader={<ListSubheader>others</ListSubheader>}>
+            {
+            othersList.map((items, index) => (
+              (items.label === 'create subreddit') ? (
+                <div key={`${index + 0}`}>
+                  <ListItemButton
+                    onClick={() => {
+                      const ele = document.getElementById('popup-form-button');
+                      console.log(ele);
+                      ele.click();
+                    }}
+                  >
+                    <ListItemIcon>
+                      {items.icon}
+                    </ListItemIcon>
+                    <ListItemText primary={items.label} />
+                  </ListItemButton>
+                  <FormDialog display="none" />
+                </div>
+              )
+                : (items.label === 'create post')
+                  ? (
+                    <ListItemButton key={`${index + 0}`}>
+                      <Link to="/submit" style={{ textDecoration: 'none', display: 'flex' }}>
+                        <ListItemIcon>
+                          {items.icon}
+                        </ListItemIcon>
+                        <ListItemText primary={items.label} />
+                      </Link>
+                    </ListItemButton>
+                  )
+                  : (items.label === 'notifications')
+                    ? (
+                      <ListItemButton key={`${index + 0}`}>
+                        <Link to="/notifications" style={{ textDecoration: 'none', display: 'flex' }}>
+                          <ListItemIcon>
+                            {items.icon}
+                          </ListItemIcon>
+                          <ListItemText primary={items.label} />
+                        </Link>
+                      </ListItemButton>
+                    )
+                    : (items.label === 'top communities')
+                      ? (
+                        <ListItemButton key={`${index + 0}`}>
+                          <Link to="/subreddits/leaderboard/" style={{ textDecoration: 'none', display: 'flex' }}>
+                            <ListItemIcon>
+                              {items.icon}
+                            </ListItemIcon>
+                            <ListItemText primary={items.label} />
+                          </Link>
+                        </ListItemButton>
+                      )
+                      : (items.label === 'user settings')
+                        ? (
+                          <ListItemButton key={`${index + 0}`}>
+                            <Link to="/settings" style={{ textDecoration: 'none', display: 'flex' }}>
+                              <ListItemIcon>
+                                {items.icon}
+                              </ListItemIcon>
+                              <ListItemText primary={items.label} />
+                            </Link>
+                          </ListItemButton>
+                        ) : (
+                          <ListItemButton key={`${index + 0}`}>
+                            <Link to="/messages" style={{ textDecoration: 'none', display: 'flex' }}>
+                              <ListItemIcon>
+                                {items.icon}
+                              </ListItemIcon>
+                              <ListItemText primary={items.label} />
+                            </Link>
+                          </ListItemButton>
+                        )
+            ))
+            }
+          </List>
+        </Collapse>
+      </StyledList>
+    </ClickAwayListener>
+  );
+}
+
+export default HomeList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_Navbar_Logo_logoIcon.jsx.html b/docs/components_MainNavBar_Navbar_Logo_logoIcon.jsx.html new file mode 100644 index 00000000..4235d43e --- /dev/null +++ b/docs/components_MainNavBar_Navbar_Logo_logoIcon.jsx.html @@ -0,0 +1,77 @@ + + + + + JSDoc: Source: components/MainNavBar/Navbar/Logo/logoIcon.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/Navbar/Logo/logoIcon.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import { Link } from 'react-router-dom';
+import LogoText from '../assests/LogoText.svg';
+import Logo from '../assests/Logo.svg';
+/**
+ * LogoIcon
+ * @component
+ * Both of the logo and word are hyperlinks to the homepage.
+ * @returns {React.Component} logo and nonlegit word beside it.
+ */
+function LogoIcon() {
+  return (
+    <Link to="/" style={{ textDecoration: 'none' }}>
+      <Box sx={{ display: 'flex' }}>
+        <Box sx={{ padding: '8px 8px 8px 0px', display: 'flex', justifyContent: 'center' }}>
+          <img alt="" src={Logo} width={32} height={32} />
+        </Box>
+        <Box sx={{ display: { xs: 'none', lg: 'flex' }, alignItems: 'center', paddingBottom: '4px' }}>
+          <img alt="" src={LogoText} width={57} height={20} />
+        </Box>
+      </Box>
+    </Link>
+  );
+}
+
+export default LogoIcon;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_Navbar_NavIcons_NavIcons.jsx.html b/docs/components_MainNavBar_Navbar_NavIcons_NavIcons.jsx.html new file mode 100644 index 00000000..ee90d6d3 --- /dev/null +++ b/docs/components_MainNavBar_Navbar_NavIcons_NavIcons.jsx.html @@ -0,0 +1,231 @@ + + + + + JSDoc: Source: components/MainNavBar/Navbar/NavIcons/NavIcons.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/Navbar/NavIcons/NavIcons.jsx

+ + + + + + +
+
+
/* eslint-disable react/jsx-no-constructed-context-values */
+import AddIcon from '@mui/icons-material/Add';
+import Badge from '@mui/material/Badge';
+import { grey } from '@mui/material/colors';
+import OutboundOutlinedIcon from '@mui/icons-material/OutboundOutlined';
+import NotificationsNoneIcon from '@mui/icons-material/NotificationsNone';
+import {
+  IconButton, Zoom, Box, Button,
+} from '@mui/material';
+import { Link, useNavigate } from 'react-router-dom';
+import { useState, useEffect } from 'react';
+import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined';
+import BeenhereOutlinedIcon from '@mui/icons-material/BeenhereOutlined';
+import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
+import { onForegroundNottification } from '../../../../lib/firebase';
+import {
+  StyledTooltip, NotificationButton, NotificationContent, NotificationContanier,
+  NotificationHeaderIcons, NotificationIcons, LinkTo, SeeAll,
+} from './styles';
+import notificationsFetch from '../../../Notifications/notificationsServer';
+import NotificationCategories from '../../../Notifications/NotificationsBody/NotificationCategories/NotificationCategories';
+import { CategoriesContext } from '../../../Notifications/NotificationsBody/NotificationsBody';
+
+/**
+ *  NavIcons
+ * @component
+ * @returns {React.Component} the three icons in the navbar (Popular - notifications - create post)
+ */
+function NavIcons() {
+  const navigate = useNavigate();
+  const handleRoutePopular = () => {
+    navigate('/r/popular');
+  };
+  const [today, setToday] = useState([]);
+  const [select, setSelect] = useState(null);
+  const [dataToday, dataEarlier] = notificationsFetch();
+  //  anchor element
+  const [anchorEl, setAnchorEl] = useState(null);
+  const [unread, setUnread] = useState(0);
+  const [message, setMessage] = useState(false);
+  const [anchorElWindow, setAnchorElWindow] = useState(null);
+  const openWindow = Boolean(anchorElWindow);
+  const open = Boolean(anchorEl);
+  const handleClick = (event) => {
+    setAnchorElWindow(event.currentTarget);
+  };
+  const handleCloseWindow = () => {
+    setAnchorElWindow(null);
+  };
+  useEffect(() => {
+    const data = dataToday.concat(dataEarlier);
+    setToday(data.slice(0, 5));
+  }, [dataEarlier, dataToday]);
+  useEffect(() => {
+    onForegroundNottification()
+      .then((payload) => {
+        const { data: { val } } = payload;
+        const value = JSON.parse(val);
+        if (value.type === 'follow' || value.type === 'commentReply' || value.type === 'userMention' || value.type === 'firstPostUpVote' || value.type === 'firstCommentUpVote') { setToday((oldArray) => [value, ...oldArray]); } else {
+          setMessage(true);
+        }
+        if (value.type === 'postReply') {
+          setToday((oldArray) => [value, ...oldArray]);
+        }
+        setUnread(unread + 1);
+      })
+      .catch((err) => console.log('An error occured while retrieving foreground message. ', err));
+  });
+  const handleClose = (event) => {
+    const tabindex = event.currentTarget.getAttribute('tabindex');
+    if (select !== null && tabindex === '0') {
+      setToday(
+        today.filter((e, i) => i !== Number(select)),
+      );
+      setSelect(null);
+    }
+    setAnchorEl(null);
+  };
+  return (
+    <Box sx={{ alignItems: 'flex-start', display: { xs: 'none', sm: 'flex' }, flexDirection: 'row' }}>
+      <StyledTooltip
+        title="Popular"
+        TransitionComponent={Zoom}
+        enterDelay={700}
+        enterNextDelay={700}
+      >
+        <IconButton
+          size="large"
+          aria-label="show 17 new notifications"
+          color="inherit"
+          sx={{ '&:hover': { backgroundColor: 'transparent' } }}
+          onClick={handleRoutePopular}
+        >
+          <OutboundOutlinedIcon sx={{ color: grey[600], fontSize: 25 }} />
+        </IconButton>
+      </StyledTooltip>
+      <Button
+        id="basic-button"
+        aria-controls={openWindow ? 'basic-menu' : undefined}
+        aria-haspopup="true"
+        aria-expanded={openWindow ? 'true' : undefined}
+        onClick={handleClick}
+        disableRipple
+        sx={{
+          '&:hover': {
+            backgroundColor: 'transparent',
+          },
+        }}
+      >
+        <NotificationButton
+          disableRipple
+          size="large"
+          aria-label={`show ${unread} new notifications`}
+          color="inherit"
+        >
+          <Badge badgeContent={unread} color="error">
+            <NotificationsNoneIcon sx={{ color: grey[600], fontSize: 25 }} />
+          </Badge>
+        </NotificationButton>
+      </Button>
+      <NotificationContanier
+        disableRipple
+        id="basic-menu"
+        anchorEl={anchorElWindow}
+        open={openWindow}
+        onClose={handleCloseWindow}
+        MenuListProps={{
+          'aria-labelledby': 'basic-button',
+        }}
+      >
+        <NotificationContent disableRipple>
+          Notifications
+          <NotificationHeaderIcons>
+            <LinkTo to="/messages/unread" sx={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
+              { (message) && <ErrorOutlineIcon fontWeight="bold" color="error" />}
+              {' '}
+              Messages
+            </LinkTo>
+            <NotificationIcons>
+              <BeenhereOutlinedIcon />
+            </NotificationIcons>
+            <NotificationIcons>
+              <SettingsOutlinedIcon />
+            </NotificationIcons>
+          </NotificationHeaderIcons>
+
+        </NotificationContent>
+        <NotificationContent disableRipple>
+          <CategoriesContext.Provider value={{
+            today, handleClose, handleClick, open, anchorEl,
+          }}
+          >
+            <NotificationCategories NavBar />
+          </CategoriesContext.Provider>
+        </NotificationContent>
+        <SeeAll to="/notifications" onClick={handleCloseWindow}>
+          SEE ALL
+        </SeeAll>
+      </NotificationContanier>
+
+      <StyledTooltip
+        title="Add Post"
+        TransitionComponent={Zoom}
+        enterDelay={700}
+        enterNextDelay={700}
+      >
+        <IconButton
+          sx={{ '&:hover': { backgroundColor: 'transparent' } }}
+        >
+          <Link to="/submit">
+            <AddIcon sx={{ color: 'grey', fontSize: 30 }} />
+          </Link>
+        </IconButton>
+      </StyledTooltip>
+
+    </Box>
+  );
+}
+
+export default NavIcons;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_Navbar_Navbar.jsx.html b/docs/components_MainNavBar_Navbar_Navbar.jsx.html new file mode 100644 index 00000000..ee549f33 --- /dev/null +++ b/docs/components_MainNavBar_Navbar_Navbar.jsx.html @@ -0,0 +1,102 @@ + + + + + JSDoc: Source: components/MainNavBar/Navbar/Navbar.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/Navbar/Navbar.jsx

+ + + + + + +
+
+
/* eslint-disable no-unused-vars */
+import { Box } from '@mui/material';
+import MuiToolbar from '@mui/material/Toolbar';
+import StyledNavbar from './styles';
+import HomeList from './HomeList/HomeList';
+import UserList from './UserList/UserList';
+import SearchButton from '../Search/Search';
+import NavIcons from './NavIcons/NavIcons';
+import LogoIcon from './Logo/logoIcon';
+/**
+ * Navbar
+ * @component
+ * @returns {React.Component} the whole logged in navbar with the two lists,
+ * Search bar and icon buttons
+ */
+function Navbar() {
+  const pathArray = window.location.pathname.split('/');
+  return (
+    window.location.pathname !== '/login'
+    && window.location.pathname !== '/password'
+    && window.location.pathname !== '/register'
+    && window.location.pathname !== '/username'
+    && pathArray[1] !== 'resetpassword'
+    && pathArray[1] !== 'verification'
+    && (
+    <StyledNavbar>
+      <MuiToolbar>
+        <Box sx={{
+          display: 'flex', width: '100%', alignItems: 'center', flexGrow: 1,
+        }}
+        >
+          <LogoIcon />
+          <HomeList />
+          <SearchButton />
+        </Box>
+        <Box sx={{
+          display: 'flex', alignItems: 'center', justifyContent: 'flex-end',
+        }}
+        >
+          <NavIcons />
+
+          <UserList />
+
+        </Box>
+      </MuiToolbar>
+    </StyledNavbar>
+    )
+  );
+}
+
+export default Navbar;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_Navbar_UserList_UserList.jsx.html b/docs/components_MainNavBar_Navbar_UserList_UserList.jsx.html new file mode 100644 index 00000000..be762d04 --- /dev/null +++ b/docs/components_MainNavBar_Navbar_UserList_UserList.jsx.html @@ -0,0 +1,236 @@ + + + + + JSDoc: Source: components/MainNavBar/Navbar/UserList/UserList.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/Navbar/UserList/UserList.jsx

+ + + + + + +
+
+
/* eslint-disable no-unsafe-optional-chaining */
+/* eslint-disable react/no-array-index-key */
+import {
+  List, ListItemButton, ListItemIcon, Collapse, Box, Typography, Divider, ListItemText, ClickAwayListener,
+} from '@mui/material';
+import { useNavigate, Link } from 'react-router-dom';
+import ExpandMore from '@mui/icons-material/ExpandMore';
+import ExpandLess from '@mui/icons-material/ExpandLess';
+import Avatar from '@mui/material/Avatar';
+import * as React from 'react';
+import AccountCircleOutlinedIcon from '@mui/icons-material/AccountCircleOutlined';
+import LoginOutlinedIcon from '@mui/icons-material/LoginOutlined';
+import AutoFixHighOutlinedIcon from '@mui/icons-material/AutoFixHighOutlined';
+
+import { useCookies } from 'react-cookie';
+import { redditCookie } from '../../../Authentication/authenticationServer';
+import FormDialog from '../../../HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/PopUp';
+import {
+  StyledList,
+} from './styles';
+import karma from '../assests/karma.png';
+import { firstList, secondList, exploreList } from './Lists';
+import { logOut } from './server';
+/**
+ * UserList
+ * @component
+ * @returns {React.Component} the User list which is the right lish in logged in navbar.
+ */
+
+function UserList() {
+  // navigate
+  const navigate = useNavigate();
+  const handleClick = (subPage) => {
+    navigate(`/t/${subPage}/`);
+  };
+  // eslint-disable-next-line no-unused-vars
+  const [cookies, setCookie, removeCookie] = useCookies(['redditUser']);
+  React.useEffect(() => {
+    redditCookie(setCookie);
+  }, []);
+  const [openUserList, setOpenUserList] = React.useState(0);
+  const handleClickUserList = () => {
+    setOpenUserList(!openUserList);
+  };
+
+  const [openExploreList, setOpenExploreList] = React.useState(0);
+  const handleClickExploreList = () => {
+    setOpenExploreList(!openExploreList);
+  };
+
+  const [openSubList, setOpenSubList] = React.useState([0, 0, 0, 0, 0, 0, 0]);
+  const handleClickSubList = (index) => {
+    const arr = [0, 0, 0, 0, 0, 0, 0];
+    arr[index] = (openSubList[index] === 1) ? 0 : 1;
+    setOpenSubList(arr);
+  };
+
+  return (
+    <ClickAwayListener onClickAway={() => { setOpenUserList(false); }}>
+      <StyledList>
+
+        <ListItemButton onClick={handleClickUserList}>
+
+          <Box sx={{ display: 'flex', alignItems: 'center' }}>
+            <ListItemIcon>
+              <Box>
+                <Avatar src={cookies.redditUser?.profilePicture} />
+              </Box>
+            </ListItemIcon>
+            <Box sx={{ display: { xs: 'none', md: 'flex' }, flexDirection: 'column', paddingRight: '60px' }}>
+              <Typography sx={{ fontSize: '12px', color: '#1C1C1C' }}>{cookies.redditUser?.userName}</Typography>
+              <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
+                <img alt="" src={karma} width={12} height={12} />
+                <Typography sx={{ fontSize: '12px', color: '#A8AAAB', whiteSpace: 'nowrap' }}>
+                  { cookies.redditUser?.postKarma + cookies.redditUser?.commentKarma }
+                  {' '}
+                  karma
+                </Typography>
+              </Box>
+            </Box>
+          </Box>
+          <ExpandMore sx={{ color: '#757575', fontSize: 20 }} />
+        </ListItemButton>
+
+        <Collapse in={Boolean(openUserList)} timeout="auto" unmountOnExit>
+          <List component="div" disablePadding sx={{ position: 'absolute', width: '100%' }}>
+            <ListItemButton>
+              <ListItemIcon sx={{ display: 'contents' }}>
+                <AccountCircleOutlinedIcon sx={{ color: '#787C7E' }} />
+              </ListItemIcon>
+              <ListItemText primary="my stuff" />
+            </ListItemButton>
+            {
+            firstList.map((items, index) => (
+              <ListItemButton key={`${index + 0}`}>
+                { (items === 'profile')
+                  ? (
+                    <Link to={`/user/${cookies.redditUser?.userName}`} style={{ textDecoration: 'none', display: 'flex', width: '100%' }}>
+                      <ListItemText primary={items} />
+                    </Link>
+                  )
+                  : (items === 'user settings')
+                    ? (
+                      <Link to="/settings" style={{ textDecoration: 'none', display: 'flex', width: '100%' }}>
+                        <ListItemText primary={items} />
+                      </Link>
+                    )
+                    : (
+                      <ListItemText primary={items} />
+
+                    )}
+              </ListItemButton>
+            ))
+          }
+            <Divider sx={{ borderColor: '#cacbcd' }} />
+            { secondList.map((items, index) => (
+              (items.label === 'create a community')
+                ? (
+                  <div key={`${index + 0}`}>
+                    <ListItemButton
+                      onClick={() => {
+                        const ele = document.getElementById('popup-form-button');
+                        console.log(ele);
+                        ele.click();
+                      }}
+                    >
+                      <ListItemIcon sx={{ display: 'contents' }}>
+                        {items.icon}
+                      </ListItemIcon>
+                      <ListItemText primary={items.label} />
+                    </ListItemButton>
+
+                    <FormDialog display="none" />
+                  </div>
+                ) : (
+                  <ListItemButton key={`${index + 0}`}>
+                    <ListItemIcon sx={{ display: 'contents' }}>
+                      {items.icon}
+                    </ListItemIcon>
+                    <ListItemText primary={items.label} />
+                  </ListItemButton>
+                )
+            ))}
+            <ListItemButton onClick={handleClickExploreList}>
+              <ListItemIcon sx={{ display: 'contents' }}>
+                <AutoFixHighOutlinedIcon />
+              </ListItemIcon>
+              <ListItemText primary="Explore" />
+              {openExploreList ? <ExpandLess sx={{ color: '#000000', fontSize: 20 }} /> : <ExpandMore sx={{ color: '#000000', fontSize: 20 }} />}
+            </ListItemButton>
+            <Collapse in={Boolean(openExploreList)} timeout="auto" unmountOnExit>
+              {
+                exploreList.map((Sub, index) => (
+                  <div key={`${index + 0}`}>
+                    <ListItemButton onClick={() => { handleClickSubList(index); }}>
+                      <ListItemText primary={Sub.SubList} />
+                      {openSubList[index] ? <ExpandLess sx={{ color: '#000000', fontSize: 20 }} /> : <ExpandMore sx={{ color: '#000000', fontSize: 20 }} />}
+                    </ListItemButton>
+                    <Collapse in={Boolean(openSubList[index])} timeout="auto" unmountOnExit>
+                      {Sub.Content.map((items) => (
+                        <ListItemButton key={`${index + 0}`} onClick={() => handleClick(items)}>
+                          <ListItemText primary={items} />
+                        </ListItemButton>
+                      ))}
+                    </Collapse>
+                  </div>
+                ))
+              }
+            </Collapse>
+            <Divider sx={{ borderColor: '#cacbcd' }} />
+            <ListItemButton onClick={() => { console.log('clicked'); logOut(removeCookie); }}>
+              <ListItemIcon sx={{ display: 'contents' }}>
+                <LoginOutlinedIcon sx={{ color: 'black', fontSize: 25 }} />
+              </ListItemIcon>
+              <ListItemText primary="log out" />
+            </ListItemButton>
+          </List>
+        </Collapse>
+
+      </StyledList>
+    </ClickAwayListener>
+  );
+}
+
+export default UserList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_Search_Search.jsx.html b/docs/components_MainNavBar_Search_Search.jsx.html new file mode 100644 index 00000000..33de7d7f --- /dev/null +++ b/docs/components_MainNavBar_Search_Search.jsx.html @@ -0,0 +1,118 @@ + + + + + JSDoc: Source: components/MainNavBar/Search/Search.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/Search/Search.jsx

+ + + + + + +
+
+
import SearchIcon from '@mui/icons-material/Search';
+import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
+import { InputBase } from '@mui/material';
+import * as React from 'react';
+import { useNavigate } from 'react-router-dom';
+import { Search, StyledChip } from './styles';
+
+/**
+ * SearchField Sign Navbar
+ * @component
+ * @returns {React.Component} the search bar in the navbar.
+ */
+
+function SearchField() {
+  const navigate = useNavigate();
+
+  const [isEmpty, setIsEmpty] = React.useState(1);
+  const [query, setQuery] = React.useState('');
+  const [chipShow, setchipShow] = React.useState(0);
+  const [chipLabel, setchipLabel] = React.useState('');
+
+  React.useEffect(() => {
+    if (query.length === 0) { setIsEmpty(true); } else { setIsEmpty(false); }
+  }, [query]);
+
+  const handleClick = () => {
+    setQuery('');
+  };
+
+  const handleChange = (e) => {
+    setQuery(e.target.value);
+  };
+
+  const handleKeyDown = (e) => {
+    if (e.key === 'Enter') {
+      navigate(`search/?q=${query}`);
+      setchipLabel(query);
+      setchipShow(true);
+      setQuery('');
+    } else if (e.key === 'Backspace' && query.length === 0) {
+      setchipShow(false);
+    }
+  };
+
+  const handleDelete = () => {
+    setchipShow(false);
+  };
+
+  return (
+    <Search>
+      <SearchIcon />
+      <StyledChip chipShow={chipShow} label={chipLabel} onDelete={handleDelete} />
+      <InputBase
+        id="nav_search"
+        onChange={handleChange}
+        onKeyDown={handleKeyDown}
+        placeholder="Search nonlegit"
+        value={query}
+      />
+      {
+        !isEmpty && <CancelOutlinedIcon color="black" onClick={handleClick} />
+      }
+    </Search>
+  );
+}
+
+export default SearchField;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_SignNavbar_DrawerBottom_DrawerBottom.jsx.html b/docs/components_MainNavBar_SignNavbar_DrawerBottom_DrawerBottom.jsx.html new file mode 100644 index 00000000..64a0f1ab --- /dev/null +++ b/docs/components_MainNavBar_SignNavbar_DrawerBottom_DrawerBottom.jsx.html @@ -0,0 +1,86 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/DrawerBottom/DrawerBottom.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/DrawerBottom/DrawerBottom.jsx

+ + + + + + +
+
+
import { Typography } from '@mui/material';
+import StyledBottom from './styles';
+import RedditButton from '../RedditButton/RedditButton';
+
+/**
+ * DrawerBottom
+ * @component
+ * @param {logInPopup} param0 opening the register popup window
+ * @returns {React.Component} the bottom of the left permanent sidebar
+ */
+function DrawerBottom({ logInPopup }) {
+  return (
+    <StyledBottom>
+      <Typography>_____________________________</Typography>
+      <Typography>
+        Create an account to follow your favorite communities
+        and start taking part in conversations.
+      </Typography>
+      <RedditButton
+        data-testid="drawer-login"
+        fontSize="14px"
+        padding="4px 16px"
+        fontWeight="700"
+        variant="contained"
+        margin="0px"
+        onClick={logInPopup}
+        sx={{ width: '225px', height: '40px' }}
+      >
+        Join Reddit
+      </RedditButton>
+    </StyledBottom>
+  );
+}
+
+export default DrawerBottom;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_SignNavbar_Drawer_Drawer.jsx.html b/docs/components_MainNavBar_SignNavbar_Drawer_Drawer.jsx.html new file mode 100644 index 00000000..65dae844 --- /dev/null +++ b/docs/components_MainNavBar_SignNavbar_Drawer_Drawer.jsx.html @@ -0,0 +1,120 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/Drawer/Drawer.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/Drawer/Drawer.jsx

+ + + + + + +
+
+
/* eslint-disable react/no-array-index-key */
+import Box from '@mui/material/Box';
+import Toolbar from '@mui/material/Toolbar';
+import Divider from '@mui/material/Divider';
+import ExpandMore from '@mui/icons-material/ExpandMore';
+import ExpandLess from '@mui/icons-material/ExpandLess';
+import {
+  ListSubheader, ListItemIcon, ListItemText, ListItemButton, ListItem, List, Collapse,
+} from '@mui/material';
+import * as React from 'react';
+import { firstList, exploreList } from './Lists';
+import StyledDrawer from './styles';
+
+/**
+ * Drawer
+ * @component
+ * @returns {React.Component} the side bar that permenantely appears on the left on the page
+ *  in case of signed out
+ */
+export default function Drawer() {
+  const [openSubList, setOpenSubList] = React.useState([0, 0, 0, 0, 0, 0, 0]);
+  const handleClickSubList = (index) => {
+    const arr = [0, 0, 0, 0, 0, 0, 0];
+    arr[index] = (openSubList[index] === 1) ? 0 : 1;
+    setOpenSubList(arr);
+  };
+  return (
+    <StyledDrawer variant="permanent">
+      <Toolbar />
+      <Box sx={{ overflow: 'auto' }}>
+        <List subheader={<ListSubheader>FEEDS</ListSubheader>}>
+          {firstList.map((items, index) => (
+            <ListItem disablePadding key={index}>
+              <ListItemButton>
+                <ListItemIcon>
+                  {items.icon}
+                </ListItemIcon>
+                <ListItemText primary={items.label} />
+              </ListItemButton>
+            </ListItem>
+          ))}
+        </List>
+        <Divider />
+        <List subheader={<ListSubheader>TOPICS</ListSubheader>}>
+          {
+          exploreList.map((Sub, index) => (
+            <>
+              <ListItemButton key={`${index + 0}`} onClick={() => { handleClickSubList(index); }}>
+                <ListItemIcon>
+                  {Sub.icon}
+                </ListItemIcon>
+                <ListItemText primary={Sub.SubList} />
+                {openSubList[index] ? <ExpandLess sx={{ color: '#000000', fontSize: 20 }} /> : <ExpandMore sx={{ color: '#000000', fontSize: 20 }} />}
+              </ListItemButton>
+              <Collapse in={Boolean(openSubList[index])} timeout="auto" unmountOnExit>
+                {Sub.Content.map((items) => (
+                  <ListItemButton key={`${index + 0}`}>
+                    <ListItemText inset primary={items} />
+                  </ListItemButton>
+                ))}
+              </Collapse>
+            </>
+          ))
+          }
+        </List>
+      </Box>
+    </StyledDrawer>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_SignNavbar_ForgetPassPopUp_ForgetPass.jsx.html b/docs/components_MainNavBar_SignNavbar_ForgetPassPopUp_ForgetPass.jsx.html new file mode 100644 index 00000000..0a7f2fca --- /dev/null +++ b/docs/components_MainNavBar_SignNavbar_ForgetPassPopUp_ForgetPass.jsx.html @@ -0,0 +1,267 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/ForgetPassPopUp/ForgetPass.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/ForgetPassPopUp/ForgetPass.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import { Box, Typography } from '@mui/material';
+import * as React from 'react';
+import CloseIcon from '@mui/icons-material/Close';
+import { useEffect, useState } from 'react';
+import { useCookies } from 'react-cookie';
+import { ForgetPassContext } from '../SignNavbar';
+// import StyledDialog from '../styles';
+import {
+  StyledLink, FirstPartyContainer,
+  RedditTextField, RedditLoadingButton,
+} from '../ูAuthentication/styles';
+import AuthenticationHeader from '../../../Authentication/AuthenticationHeader/AuthenticationHeader';
+import { checkUserName, recoverPassword } from './server';
+
+import { redditCookie, checkEmail } from '../../../Authentication/authenticationServer';
+
+import theme, { fonts } from '../../../../styles/theme';
+import { StyledDialog } from '../styles';
+// ultis
+import { redirectLogin } from '../../../../utils/Redirect';
+
+/**
+ * ForgetPassword popUp
+ * @component
+ * Forget password popup different components
+ * @returns {React.Component} main body of forget password popup
+ */
+function ForgetPassword() {
+  const [loading, setLoading] = useState(false);
+  const [buttonText, setbuttonText] = useState('Reset Password');
+  const [disabled, setDisabled] = useState(false);
+  const [redirectCaption, setRedirectCaption] = useState(false);
+  const [userName, setUserName] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+  const [email, setEmail] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+
+  // cookies
+  const [cookies, setCookies, removeCookie] = useCookies(['redditUser']);
+  const {
+    openForgotpass,
+    handleClose,
+    handleClickOpenForgotUser,
+    handleClickOpenSignUp,
+    handleClickOpenLogIn,
+  } = React.useContext(ForgetPassContext);
+
+  // useEffect
+  useEffect(() => {
+    // Check on Cookies
+    // developememt
+    /// Ask if this user already loggied in the back
+    // Remove Old Cookie :)==>Of course he is signed out
+    redditCookie(setCookies, removeCookie);
+    // if logged in in the back end
+    if (cookies.redditUser !== undefined) {
+      // production
+      // Update Cookie
+      // redditCookie(setCookies);
+      // check on Reddit cookie
+      // if (cookies.redditUser === undefined) {
+      //   redditCookie(setCookies);
+      // }
+      // Redirect to loading page
+      console.log('Remember me is set to true');
+      redirectLogin(2);
+    } else {
+      // No Cookie by Back End
+      console.log('Remember me is set to false');
+    }
+  }, []);
+
+  const caption = (
+    <>
+      Tell us the username and email address associated with
+      your Reddit account, and weโ€™ll send you an email with a link to reset your password.
+    </>
+  );
+
+  return (
+    <StyledDialog
+      data-testid="forgetpass-popup"
+      fullscreen
+      open={openForgotpass}
+      aria-labelledby="alert-dialog-title"
+      aria-describedby="alert-dialog-description"
+    >
+      <Box width="280px" height="454px">
+        <CloseIcon
+          sx={{
+            position: 'absolute', right: '16px', top: '16px', cursor: 'pointer',
+          }}
+          onClick={handleClose}
+        />
+        <>
+          <AuthenticationHeader reddit={false} title="Reset your password" caption={caption} fontSize="14px" />
+          <FirstPartyContainer
+            width="280px"
+            noValidate
+            onSubmit={(e) => {
+              e.preventDefault(); recoverPassword(
+                setLoading,
+                email,
+                setEmail,
+                userName,
+                setUserName,
+                setDisabled,
+                setbuttonText,
+                setRedirectCaption,
+              );
+            }}
+          >
+            <RedditTextField
+              label="Username"
+              variant="filled"
+              type="text"
+              required
+              InputProps={{
+                endAdornment: (
+                  userName.icon
+                ),
+                disableUnderline: true,
+              }}
+              clr={userName.color}
+              onChange={(e) => {
+                setUserName((prevState) => ({
+                  ...prevState,
+                  input: e.target.value.trim(),
+                }));
+                checkUserName(e.target.value.trim(), userName.error, setUserName);
+              }}
+              helperText={userName.error}
+            />
+
+            <RedditTextField
+              label="Email Address"
+              variant="filled"
+              required
+              InputProps={{
+                endAdornment: (
+                  email.icon
+                ),
+                disableUnderline: true,
+              }}
+              clr={email.color}
+              onChange={(e) => {
+                setEmail((prevState) => ({
+                  ...prevState,
+                  input: e.target.value.trim(),
+                }));
+                checkEmail(e.target.value.trim(), setEmail);
+              }}
+              helperText={email.error}
+            />
+            <RedditLoadingButton
+              type="submit"
+              width="155px"
+              loading={loading}
+              disabled={disabled}
+            >
+              {buttonText}
+            </RedditLoadingButton>
+            {redirectCaption
+              ? (
+                <Typography color="primary" fontSize="12px" fontFamily={fonts['system-ui']} fontWeight="600" margin="20px 0px">
+                  Thanks! If your Reddit username and email address match, youโ€™ll get an email with a link to reset your password shortly.
+                </Typography>
+              )
+              : null}
+            <StyledLink
+              data-testid="forgetpass-forgetuser"
+              onClick={handleClickOpenForgotUser}
+              fontWeight="600"
+              capital="uppercase"
+            >
+              FORGOT USERNAME?
+
+            </StyledLink>
+          </FirstPartyContainer>
+          <Typography paragraph fontSize="12px" margin="10px 0px">
+            Don
+            {'\''}
+            t have an email or need assistance logging in? GET HELP
+          </Typography>
+
+          <Typography paragraph fontSize="12px" marginTop="10px" color="#3394DC">
+            <StyledLink
+              data-testid="forgetpass-login"
+              onClick={handleClickOpenLogIn}
+              fontWeight="600"
+              capital="uppercase"
+            >
+              log in
+
+            </StyledLink>
+            {' โ€ข '}
+            <StyledLink
+              data-testid="forgetpass-signup"
+              onClick={handleClickOpenSignUp}
+              fontWeight="600"
+              capital="uppercase"
+            >
+              sign up
+
+            </StyledLink>
+          </Typography>
+        </>
+      </Box>
+    </StyledDialog>
+  );
+}
+
+export default ForgetPassword;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_SignNavbar_ForgetPassPopUp_server.js.html b/docs/components_MainNavBar_SignNavbar_ForgetPassPopUp_server.js.html new file mode 100644 index 00000000..8454bc25 --- /dev/null +++ b/docs/components_MainNavBar_SignNavbar_ForgetPassPopUp_server.js.html @@ -0,0 +1,171 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/ForgetPassPopUp/server.js + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/ForgetPassPopUp/server.js

+ + + + + + +
+
+
// mui components
+import DoneIcon from '@mui/icons-material/Done';
+
+// services
+import axios from '../../../../services/instance';
+
+// styles
+import { wrongIcon, rightIcon } from '../../../Authentication/styles';
+import theme from '../../../../styles/theme';
+
+// scripts
+
+import { checkEmail } from '../../../Authentication/authenticationServer';
+
+/**
+ *
+ * @param {string} username --userName Object
+ * @param {string} error --error Message
+ * @param {setfunction}setUserName --setfunction for the userName
+ * @returns {void}
+ */
+export const checkUserName = (username, error, setUserName) => {
+  // console.log(username); //must be passed expilicity
+  // console.log('Check User');
+  // console.log(error); //must be passed expilicity
+  if (error === "That user doesn't exist") {
+    // wait for Data Base
+    return;
+  }
+  // Check Username bwteen 3-20 characters
+  if (username.length < 3 || username.length > 20) {
+    // console.log('length problem');
+    setUserName((prevState) => ({
+      ...prevState,
+      color: theme.palette.error.main,
+      icon: wrongIcon,
+      error: 'Username must be between 3 and 20 characters',
+    }));
+    return;
+  }
+  // else Valid
+  setUserName((prevState) => ({
+    ...prevState,
+    color: theme.palette.primary.main,
+    icon: rightIcon,
+    error: null,
+  }));
+};
+
+/**
+ *
+ * Recover Email
+ * @param {setfunction} setLoading
+ * @param {object} email --email object to recoverPassword with
+ * @param {object} userName --userName object to recoverPassword with
+ * @param {setFunction} setUserName --setfunction for the userName
+ * @param {setFunction} setDisabled --setfunction for the setting Button Disabled or Enabled
+ * @param {setFunction} setbuttonText --setfunction for the Button Text
+ * @param {setFunction} setRedirectCaption --setfunction for the Caption in SignUp Page
+ * @returns {void}
+ */
+export const recoverPassword = (
+  setLoading,
+  email,
+  setEmail,
+  userName,
+  setUserName,
+  setDisabled,
+  setbuttonText,
+  setRedirectCaption,
+) => {
+  // console.log(userName); //correct
+  setLoading(true);
+  // Setting error in case of first time
+  checkEmail(email.input, setEmail);
+  checkUserName(userName.input, userName.error, setUserName);
+
+  // Case he didn't enter anything
+  if (email.input === '' || userName.input === '') {
+    setLoading(false);
+    return;
+  }
+
+  // There are some errors in the email or username
+  if (userName.error !== "That user doesn't exist" && (email.error != null || userName.error != null)) {
+    setLoading(false);
+    return;
+  }
+
+  axios.post('/users/forgot_password', { email: email.input, userName: userName.input }).then((response) => {
+    if (response.status === 204 || response.status === 201 || response.status === 200) {
+      setUserName((prevState) => ({
+        ...prevState,
+        color: theme.palette.primary.main,
+        icon: rightIcon,
+        error: null,
+      }));
+      setTimeout(() => {
+        setLoading(false);
+        setDisabled(true);
+        setbuttonText(<DoneIcon />);
+        setRedirectCaption(true);
+      }, 1000);
+    }
+  }).catch((error) => {
+    setLoading(false);
+    console.log(error);
+    if (error.response?.status === 404) {
+      // This user Doesn't exist
+      setUserName((prevState) => ({
+        ...prevState,
+        color: theme.palette.error.main,
+        icon: wrongIcon,
+        error: 'That user doesn\'t exist',
+      }));
+      console.log(error.response?.errorMessage);
+    }
+    // 400 provode username and Password[Isn't reached]
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_SignNavbar_ForgetUserNamePopUp_ForgetUser.jsx.html b/docs/components_MainNavBar_SignNavbar_ForgetUserNamePopUp_ForgetUser.jsx.html new file mode 100644 index 00000000..c84ff5a6 --- /dev/null +++ b/docs/components_MainNavBar_SignNavbar_ForgetUserNamePopUp_ForgetUser.jsx.html @@ -0,0 +1,196 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/ForgetUserNamePopUp/ForgetUser.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/ForgetUserNamePopUp/ForgetUser.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import { Box, Typography } from '@mui/material';
+import * as React from 'react';
+import CloseIcon from '@mui/icons-material/Close';
+import { useEffect, useState } from 'react';
+import { useCookies } from 'react-cookie';
+
+import { ForgetUserContext } from '../SignNavbar';
+import { StyledDialog } from '../styles';
+import { StyledLink } from '../ูAuthentication/styles';
+import AuthenticationHeader from '../../../Authentication/AuthenticationHeader/AuthenticationHeader';
+import Email from '../ูAuthentication/Email/Email';
+import { recoverUsername } from './server';
+
+import { redditCookie } from '../../../Authentication/authenticationServer';
+
+import theme, { fonts } from '../../../../styles/theme';
+
+// // environment variables
+// const { REACT_APP_ENV } = process.env;
+/**
+ *  ForgetUsername popUp
+ * @component
+ * forget username popup different components
+ * @returns {React.Component} main body of forget username popup
+ */
+function ForgetUsername() {
+  // states
+  const [email, setEmail] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+  const [loading, setLoading] = useState(false);
+  const [verified, setVerified] = useState(false);
+  const [buttonText, setbuttonText] = useState('Email Me');
+  const [disabled, setDisabled] = useState(false);
+  const [redirectCaption, setRedirectCaption] = useState(false);
+  // cookies
+  // eslint-disable-next-line no-unused-vars
+  const [cookies, setCookies, removeCookie] = useCookies(['redditUser']);
+
+  const {
+    openForgotUser,
+    handleClose,
+    handleClickOpenSignUp,
+    handleClickOpenLogIn,
+  } = React.useContext(ForgetUserContext);
+
+  // useEffect
+  useEffect(() => {
+    // Check on Cookies
+    // developememt
+    /// Ask if this user already loggied in the back
+    // Remove Old Cookie :)==>Of course he is signed out
+    redditCookie(setCookies, removeCookie);
+    // if logged in in the back end
+    // if (cookies.redditUser !== undefined) {
+    //   // production
+    //   // Update Cookie
+    //   // redditCookie(setCookies);
+    //   // check on Reddit cookie
+    //   // if (cookies.redditUser === undefined) {
+    //   //   redditCookie(setCookies);
+    //   // }
+    //   // Redirect to loading page
+    //   console.log('Remember me is set to true');
+    //   handleClose();
+    //   redirectHome(100);
+    // } else {
+    //   // No Cookie by Back End
+    //   console.log('Remember me is set to false');
+    // }
+  }, []);
+
+  const caption = (
+    <>
+      Tell us the email address associated with your Reddit account, and weโ€™ll
+      send you an email with your username.
+    </>
+  );
+
+  return (
+    <StyledDialog
+      data-testid="forgetuser-popup"
+      fullScreen
+      open={openForgotUser}
+      aria-labelledby="alert-dialog-title"
+      aria-describedby="alert-dialog-description"
+    >
+      <Box width="280px" height="326px">
+        <CloseIcon
+          sx={{
+            position: 'absolute', right: '16px', top: '16px', cursor: 'pointer',
+          }}
+          onClick={handleClose}
+        />
+        <AuthenticationHeader reddit={false} title="Recover your username" caption={caption} fontSize="14px" />
+        <Email
+          email={email}
+          setEmail={setEmail}
+          onSubmitFn={() => recoverUsername(setLoading, email, verified, setDisabled, setbuttonText, setRedirectCaption)}
+          loading={loading}
+          buttonText={buttonText}
+          btnWidth="155px"
+          fieldText="Email Address"
+          recaptcha
+          setVerified={setVerified}
+          disabled={disabled}
+          isPopUp={false}
+        />
+        {redirectCaption
+          ? <Typography color="primary" fontSize="12px" fontFamily={fonts['system-ui']} fontWeight="600" margin="20px 0px" data-testid="forgetusername-redirect-caption-test">Thanks! If there are any Reddit accounts associated with that email address, youโ€™ll get an email with your usernames(s) shortly</Typography>
+          : null}
+        <Typography paragraph fontSize="12px" margin="0px 0px 10px 0px">
+          Don
+          {'\''}
+          t have an email or need assistance logging in? GET HELP
+        </Typography>
+
+        <Typography paragraph fontSize="12px" marginTop="10px" color="#3394DC">
+          <StyledLink
+            data-testid="forgetuser-login"
+            onClick={handleClickOpenLogIn}
+            fontWeight="600"
+            capital="uppercase"
+          >
+            log in
+
+          </StyledLink>
+          {' โ€ข '}
+          <StyledLink
+            data-testid="forgetuser-signup"
+            onClick={handleClickOpenSignUp}
+            fontWeight="600"
+            capital="uppercase"
+          >
+            sign up
+
+          </StyledLink>
+        </Typography>
+      </Box>
+    </StyledDialog>
+  );
+}
+
+export default ForgetUsername;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_SignNavbar_ForgetUserNamePopUp_server.js.html b/docs/components_MainNavBar_SignNavbar_ForgetUserNamePopUp_server.js.html new file mode 100644 index 00000000..2dbe73cd --- /dev/null +++ b/docs/components_MainNavBar_SignNavbar_ForgetUserNamePopUp_server.js.html @@ -0,0 +1,114 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/ForgetUserNamePopUp/server.js + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/ForgetUserNamePopUp/server.js

+ + + + + + +
+
+
// mui components
+import DoneIcon from '@mui/icons-material/Done';
+
+// services
+import axios from '../../../../services/instance';
+
+/**
+ *
+ * recover Username
+ * @returns {void}
+ */
+export const recoverUsername = (
+  setLoading,
+  email,
+  verified,
+  setDisabled,
+  setbuttonText,
+  setRedirectCaption,
+) => {
+  // console.log(email);
+  setLoading(true);
+
+  // if there is a problem with email
+  if (email.error != null) {
+    setTimeout(() => {
+      setLoading(false);
+    }, 500);
+    return;
+  }
+
+  // not verified
+  if (!verified) {
+    setLoading(false);
+    return;
+  }
+
+  // Accepted Call API
+  axios.post('/users/forgot_username', { email: email.input }).then((response) => {
+    // console.log(response);
+    if (response.status === 204 || response.status === 201 || response.status === 200) {
+      setTimeout(() => {
+        setLoading(false);
+        setDisabled(true);
+        setbuttonText(<DoneIcon />);
+        setRedirectCaption(true);
+      }, 1000);
+    }
+  }).catch((error) => {
+    setLoading(false);
+    console.log(error);
+    if (error.response?.status === 404) {
+      // email not found in DB [Don't Give the user This info]
+      setTimeout(() => {
+        setLoading(false);
+        setDisabled(true);
+        setbuttonText(<DoneIcon />);
+        setRedirectCaption(true);
+      }, 1000);
+    } else {
+      // 400 empty username or password[Won't reach this case]
+    }
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_SignNavbar_HomeList_HomeList.jsx.html b/docs/components_MainNavBar_SignNavbar_HomeList_HomeList.jsx.html new file mode 100644 index 00000000..db84ff05 --- /dev/null +++ b/docs/components_MainNavBar_SignNavbar_HomeList_HomeList.jsx.html @@ -0,0 +1,144 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/HomeList/HomeList.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/HomeList/HomeList.jsx

+ + + + + + +
+
+
/* eslint-disable react/no-array-index-key */
+import HomeIcon from '@mui/icons-material/Home';
+import {
+  List, ListItemButton, ListItemIcon, ListItemText,
+  Collapse, ListSubheader, ClickAwayListener,
+} from '@mui/material';
+import ExpandMore from '@mui/icons-material/ExpandMore';
+import * as React from 'react';
+import ExpandLess from '@mui/icons-material/ExpandLess';
+import { useNavigate } from 'react-router-dom';
+import { StyledList } from './styles';
+import { firstList, exploreList } from '../Drawer/Lists';
+
+/**
+ * Home List
+ * @component
+ * @returns {React.Component} the left list in the navbar in signed out mode.
+ */
+function HomeList() {
+  // navigate
+  const navigate = useNavigate();
+  const handleClick = (subPage) => {
+    navigate(`/t/${subPage}/`);
+  };
+  const [openHomeList, setOpenHomeList] = React.useState(0);
+  const handleClickHomeList = () => {
+    setOpenHomeList(!openHomeList);
+  };
+
+  const [openSubList, setOpenSubList] = React.useState([0, 0, 0, 0, 0, 0, 0]);
+  const handleClickSubList = (index) => {
+    const arr = [0, 0, 0, 0, 0, 0, 0];
+    arr[index] = (openSubList[index] === 1) ? 0 : 1;
+    setOpenSubList(arr);
+  };
+
+  return (
+    <ClickAwayListener onClickAway={() => { setOpenHomeList(false); }}>
+      <StyledList>
+        <ListItemButton onClick={handleClickHomeList}>
+          <ListItemIcon>
+            <HomeIcon />
+          </ListItemIcon>
+          <ListItemText primary="Home" sx={{ color: 'black', paddingLeft: '5px' }} />
+          <ExpandMore sx={{ color: '#757575', fontSize: 20 }} />
+        </ListItemButton>
+        <Collapse
+          in={Boolean(openHomeList)}
+          sx={{
+            position: 'absolute', width: '270px', left: '0px', top: '55px', height: '465px !important',
+          }}
+          timeout="auto"
+          unmountOnExit
+        >
+          <List component="div" disablePadding subheader={<ListSubheader>feeds</ListSubheader>}>
+            {firstList.map((items, index) => (
+              <ListItemButton key={`${index + 0}`}>
+                <ListItemIcon>
+                  {items.icon}
+                </ListItemIcon>
+                <ListItemText primary={items.label} />
+              </ListItemButton>
+            ))}
+          </List>
+          <List component="div" disablePadding subheader={<ListSubheader>others</ListSubheader>}>
+            {
+          exploreList.map((Sub, index) => (
+            <>
+              <ListItemButton key={`${index + 0}`} onClick={() => { handleClickSubList(index); }}>
+                <ListItemIcon>
+                  {Sub.icon}
+                </ListItemIcon>
+                <ListItemText primary={Sub.SubList} />
+                {openSubList[index] ? <ExpandLess sx={{ color: '#000000', fontSize: 20 }} /> : <ExpandMore sx={{ color: '#000000', fontSize: 20 }} />}
+              </ListItemButton>
+              <Collapse in={Boolean(openSubList[index])} timeout="auto" unmountOnExit>
+                {Sub.Content.map((items) => (
+                  <ListItemButton key={`${index + 0}`}>
+                    <ListItemText primary={items} onClick={() => handleClick(items)} />
+                  </ListItemButton>
+                ))}
+              </Collapse>
+            </>
+          ))
+          }
+          </List>
+        </Collapse>
+      </StyledList>
+    </ClickAwayListener>
+  );
+}
+
+export default HomeList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_SignNavbar_LogInPopUp_LogIn.jsx.html b/docs/components_MainNavBar_SignNavbar_LogInPopUp_LogIn.jsx.html new file mode 100644 index 00000000..2779dd3e --- /dev/null +++ b/docs/components_MainNavBar_SignNavbar_LogInPopUp_LogIn.jsx.html @@ -0,0 +1,130 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/LogInPopUp/LogIn.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/LogInPopUp/LogIn.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import { Typography, Box } from '@mui/material';
+import CloseIcon from '@mui/icons-material/Close';
+import * as React from 'react';
+import { StyledDialog } from '../styles';
+import { StyledLink } from '../ูAuthentication/styles';
+import AuthenticationHeader from '../../../Authentication/AuthenticationHeader/AuthenticationHeader';
+import ThirdParty from '../ูAuthentication/ThirdParty/ThirdParty';
+import Divider from '../../../Authentication/Divider/Divider';
+import FirstParty from '../ูAuthentication/FirstParty/FirstParty';
+import { LoginContext } from '../SignNavbar';
+
+/**
+ *  LogIn popUp
+ * @component
+ * Login popup Differenet Components
+ * @returns {React.Component} - Main Body of Login Page
+ */
+function LogIn() {
+  const caption = (
+    <>
+      By continuing, you agree to our
+      {' '}
+      <StyledLink fontWeight="400" href="https://www.redditinc.com/policies/user-agreement" capital="none">User Agreement</StyledLink>
+      {' '}
+      and
+      {' '}
+      <StyledLink fontWeight="400" href="https://www.reddit.com/policies/privacy-policy" capital="none">Privacy Policy </StyledLink>
+      .
+    </>
+  );
+
+  const {
+    openLogIn,
+    handleClose,
+    handleClickOpenForgotUser,
+    handleClickOpenForgotPass,
+    handleClickOpenSignUp,
+  } = React.useContext(LoginContext);
+
+  return (
+    <StyledDialog
+      data-testid="login-popup"
+      fullscreen
+      open={openLogIn}
+      aria-labelledby="alert-dialog-title"
+      aria-describedby="alert-dialog-description"
+    >
+      <Box width="280px" height="454px">
+        <CloseIcon
+          sx={{
+            position: 'absolute', right: '16px', top: '16px', cursor: 'pointer',
+          }}
+          onClick={handleClose}
+        />
+        <AuthenticationHeader reddit={false} title="Log in" caption={caption} />
+        <ThirdParty circular={false} />
+        <Divider />
+        <FirstParty handleClose={handleClose} />
+        <Typography paragraph fontSize="12px" fontFamily="ibm-plex-sans,sans-serif">
+          Forgot your
+          {' '}
+          <StyledLink onClick={handleClickOpenForgotUser} data-testid="login-forgetuser" fontWeight="400" capital="none">username</StyledLink>
+          {' or '}
+          <StyledLink onClick={handleClickOpenForgotPass} data-testid="login-forgetpass" fontWeight="400" capital="none">password</StyledLink>
+          {' ?'}
+        </Typography>
+
+        <Typography paragraph fontSize={12}>
+          New to Reddit?
+          {' '}
+          <StyledLink onClick={handleClickOpenSignUp} data-testid="login-signup" fontWeight="600" capital="uppercase">sign up</StyledLink>
+        </Typography>
+      </Box>
+    </StyledDialog>
+  );
+}
+
+export default LogIn;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_SignNavbar_SignNavbar.jsx.html b/docs/components_MainNavBar_SignNavbar_SignNavbar.jsx.html new file mode 100644 index 00000000..b6621ed7 --- /dev/null +++ b/docs/components_MainNavBar_SignNavbar_SignNavbar.jsx.html @@ -0,0 +1,257 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/SignNavbar.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/SignNavbar.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+/* eslint-disable react/jsx-no-constructed-context-values */
+import { Box } from '@mui/material';
+import MuiToolbar from '@mui/material/Toolbar';
+
+import HomeIcon from '@mui/icons-material/Home';
+import * as React from 'react';
+
+import { createContext } from 'react';
+// import { Sign } from 'crypto-browserify';
+import RedditButton from './RedditButton/RedditButton';
+import {
+  StyledNavbar, HomeButton,
+} from './styles';
+import SearchButton from '../Search/Search';
+import LogoIcon from '../Navbar/Logo/logoIcon';
+// import SignUp from './SignUpPopUp/SignUp';
+import LogIn from './LogInPopUp/LogIn';
+import ForgetUsername from './ForgetUserNamePopUp/ForgetUser';
+import ForgetPassword from './ForgetPassPopUp/ForgetPass';
+import UserList from './UserList/UserList';
+import PermanentDrawerLeft from './Drawer/Drawer';
+import DrawerBottom from './DrawerBottom/DrawerBottom';
+import HomeList from './HomeList/HomeList';
+import SignUpPopUp from './SignUpPopUp/SignUpPopUp';
+
+export const SignupContext = createContext();
+export const LoginContext = createContext();
+export const ForgetUserContext = createContext();
+export const ForgetPassContext = createContext();
+export const SignUpUsernameContext = createContext();
+
+/**
+ * SNavbar
+ * @component
+ * signed out mode navbar different components
+ * @returns {React.Component} main body of navbar in signed out mode
+ */
+function SignNavbar() {
+  const [openSignUp, setOpenSignUp] = React.useState(false);
+
+  const [openLogIn, setOpenLogIn] = React.useState(false);
+
+  const [openForgotUser, setOpenForgotUser] = React.useState(false);
+
+  const [openForgotpass, setOpenForgotpass] = React.useState(false);
+
+  const [openSignUpUsername, setOpenSignUpUsername] = React.useState(false);
+
+  const handleClose = () => {
+    console.log('ClosedAll');
+    setOpenForgotpass(false);
+    setOpenForgotUser(false);
+    setOpenLogIn(false);
+    setOpenSignUp(false);
+    setOpenSignUpUsername(false);
+  };
+
+  const handleClickOpenSignUp = () => {
+    handleClose();
+    setOpenSignUp(true);
+  };
+
+  const handleClickOpenSignUpUsername = () => {
+    console.log('Opened');
+    handleClose();
+    setOpenSignUpUsername(true);
+  };
+
+  const handleClickOpenLogIn = () => {
+    handleClose();
+    setOpenLogIn(true);
+  };
+
+  const handleClickOpenForgotUser = () => {
+    handleClose();
+    setOpenForgotUser(true);
+  };
+
+  const handleClickOpenForgotPass = () => {
+    handleClose();
+    setOpenForgotpass(true);
+  };
+
+  const pathArray = window.location.pathname.split('/');
+  return (
+    window.location.pathname !== '/login'
+    && window.location.pathname !== '/password'
+    && window.location.pathname !== '/register'
+    && window.location.pathname !== '/username'
+    && pathArray[1] !== 'resetpassword'
+    && pathArray[1] !== 'verification'
+    && (
+    <>
+      <StyledNavbar>
+        <MuiToolbar>
+          <Box sx={{
+            display: 'flex', width: '100%', alignItems: 'center', flexGrow: 1,
+          }}
+          >
+            <Box sx={{ display: 'flex', alignItems: 'center', width: '100%' }}>
+              <LogoIcon />
+              <HomeList />
+
+              <HomeButton
+                sx={{
+                  display: { xs: 'none', lg: 'none' },
+                }}
+                startIcon={<HomeIcon />}
+              >
+                Home
+              </HomeButton>
+              <SearchButton />
+
+            </Box>
+          </Box>
+          <Box sx={{
+            display: 'flex', alignItems: 'center', justifyContent: 'flex-end',
+          }}
+          >
+            <Box sx={{ display: 'flex', width: 'auto' }}>
+              <RedditButton
+                data-testid="navbar-signup"
+                fontSize="14px"
+                padding="4px 16px"
+                fontWeight="700"
+                variant="outlined"
+                margin="0px"
+                onClick={handleClickOpenSignUp}
+              >
+                sign up
+              </RedditButton>
+              <RedditButton
+                data-testid="navbar-login"
+                fontSize="14px"
+                padding="4px 16px"
+                fontWeight="700"
+                variant="contained"
+                margin="0px 0px 0px 16px"
+                onClick={handleClickOpenLogIn}
+              >
+                log in
+              </RedditButton>
+            </Box>
+
+            <SignupContext.Provider value={{
+              openSignUp,
+              handleClose,
+              handleClickOpenLogIn,
+              handleClickOpenSignUp,
+              openSignUpUsername,
+              handleClickOpenSignUpUsername,
+            }}
+            >
+              <SignUpPopUp />
+            </SignupContext.Provider>
+
+            <LoginContext.Provider value={{
+              openLogIn,
+              handleClose,
+              handleClickOpenForgotUser,
+              handleClickOpenForgotPass,
+              handleClickOpenSignUp,
+            }}
+            >
+              <LogIn />
+            </LoginContext.Provider>
+
+            <ForgetUserContext.Provider value={{
+              openForgotUser,
+              handleClose,
+              handleClickOpenSignUp,
+              handleClickOpenLogIn,
+            }}
+            >
+              <ForgetUsername />
+            </ForgetUserContext.Provider>
+
+            <ForgetPassContext.Provider value={{
+              openForgotpass,
+              handleClose,
+              handleClickOpenForgotUser,
+              handleClickOpenSignUp,
+              handleClickOpenLogIn,
+            }}
+            >
+              <ForgetPassword />
+            </ForgetPassContext.Provider>
+
+            <UserList logInPopup={handleClickOpenLogIn} />
+          </Box>
+        </MuiToolbar>
+      </StyledNavbar>
+      <Box sx={{
+        display: { xs: 'none', lg: 'none' }, flexDirection: 'column', justifyContent: 'center', alignItems: 'center', position: 'absolute',
+      }}
+      >
+        <PermanentDrawerLeft />
+        <DrawerBottom logInPopup={handleClickOpenLogIn} />
+      </Box>
+    </>
+    )
+  );
+}
+
+export default SignNavbar;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_SignNavbar_SignUpPopUp_SignUp.jsx.html b/docs/components_MainNavBar_SignNavbar_SignUpPopUp_SignUp.jsx.html new file mode 100644 index 00000000..7e4b03e6 --- /dev/null +++ b/docs/components_MainNavBar_SignNavbar_SignUpPopUp_SignUp.jsx.html @@ -0,0 +1,162 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/SignUpPopUp/SignUp.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/SignUpPopUp/SignUp.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import { Box, Typography } from '@mui/material';
+import { useContext, useState, useEffect } from 'react';
+import CloseIcon from '@mui/icons-material/Close';
+import { SignupContext } from '../SignNavbar';
+import StyledDialog from '../styles';
+import {
+  StyledLink, wrongIcon,
+} from '../ูAuthentication/styles';
+import theme from '../../../../styles/theme/index';
+
+import AuthenticationHeader from
+  '../../../Authentication/AuthenticationHeader/AuthenticationHeader';
+import ThirdParty from '../ูAuthentication/ThirdParty/ThirdParty';
+import Divider from '../../../Authentication/Divider/Divider';
+import Email from '../ูAuthentication/Email/Email';
+/**
+ * SignUp popUp
+ * @component
+ * @param {setUserNamePage} param0
+ * @param {setEmail} param1 used for animate the email input field
+ * @returns {React.Component} sign up popup different component
+ * main body of sign up popup
+ */
+function SignUp({ setUserNamePage, setEmail }) {
+  const [loading, setLoading] = useState(false);
+  useEffect(() => {
+    console.log('rerender');
+  }, []);
+
+  const continueEmail = (event, email) => {
+    setLoading(true);
+    event.preventDefault();
+    console.log(email);
+    if (email.error !== null) {
+      setLoading(false);
+      return;
+    }
+
+    if (email.input === '') {
+      // Empty Field
+      setEmail((prevState) => ({
+        ...prevState,
+        color: theme.palette.error.main,
+        icon: wrongIcon,
+        error: 'Please enter your email to continue',
+      }));
+      setLoading(false);
+      return;
+    }
+    setTimeout(() => {
+      setLoading(false);
+      setUserNamePage(true);
+      console.log(email);
+    }, 500);
+  };
+
+  const caption = (
+    <>
+      By continuing, you are setting up a Reddit account and agree to our
+      {' '}
+      <StyledLink fontWeight="400" href="https://www.redditinc.com/policies/user-agreement" capital="none">User Agreement</StyledLink>
+      {' '}
+      and
+      {' '}
+      <StyledLink fontWeight="400" href="https://www.reddit.com/policies/privacy-policy" capital="none">Privacy Policy </StyledLink>
+      .
+    </>
+  );
+
+  const {
+    openSignUp, handleClose, handleClickOpenLogIn,
+  } = useContext(SignupContext);
+  return (
+    <StyledDialog
+      data-testid="signup-popup"
+      fullScreen
+      open={openSignUp}
+      aria-labelledby="alert-dialog-title"
+      aria-describedby="alert-dialog-description"
+    >
+      <Box width="280px" height="454px">
+        <CloseIcon
+          sx={{
+            position: 'absolute', right: '16px', top: '16px', cursor: 'pointer',
+          }}
+          onClick={handleClose}
+        />
+        <AuthenticationHeader reddit={false} title="Sign up" caption={caption} />
+        <ThirdParty circular={false} />
+        <Divider />
+        <Email onSubmitFn={continueEmail} loading={loading} ispopup="false" width="280px" buttonText="continue" />
+        <Typography paragraph fontSize={12}>
+          Already a redditor?
+          {' '}
+          <StyledLink
+            data-testid="signup-login"
+            onClick={handleClickOpenLogIn}
+            fontWeight="600"
+            capital="uppercase"
+          >
+            log in
+
+          </StyledLink>
+        </Typography>
+      </Box>
+    </StyledDialog>
+  );
+}
+
+export default SignUp;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_SignNavbar_SignUpPopUp_SignUpPopUpUserName_SignUpPopUpUserName.jsx.html b/docs/components_MainNavBar_SignNavbar_SignUpPopUp_SignUpPopUpUserName_SignUpPopUpUserName.jsx.html new file mode 100644 index 00000000..0233a2e6 --- /dev/null +++ b/docs/components_MainNavBar_SignNavbar_SignUpPopUp_SignUpPopUpUserName_SignUpPopUpUserName.jsx.html @@ -0,0 +1,267 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/SignUpPopUp/SignUpPopUpUserName/SignUpPopUpUserName.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/SignUpPopUp/SignUpPopUpUserName/SignUpPopUpUserName.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import { useState, useEffect, useContext } from 'react';
+
+// mui components
+import {
+  Box, Typography, InputAdornment,
+} from '@mui/material';
+import PublishedWithChangesIcon from '@mui/icons-material/PublishedWithChanges';
+
+import ArrowBackIcon from '@mui/icons-material/ArrowBack';
+import CloseIcon from '@mui/icons-material/Close';
+
+// Componenets
+import PasswordStrengthBar from 'react-password-strength-bar';
+import ReCAPTCHA from 'react-google-recaptcha';
+import AuthenticationHeader from '../../../../Authentication/AuthenticationHeader/AuthenticationHeader';
+// contexts
+import { SignupContext } from '../../SignNavbar';
+
+// server
+
+import { checkUserNameSignUp, signUp, generateRandomUsernamesServer } from '../../../../Authentication/SignUp/SignUpUsername/signupUsernameServer';
+
+// scripts
+import { checkPassword } from '../../../../Authentication/authenticationServer';
+
+// styles
+import { StyledDialog } from '../../styles';
+import { RedditTextField, RedditLoadingButton } from '../../ูAuthentication/styles';
+import theme, { fonts } from '../../../../../styles/theme';
+
+// env Variables
+const { REACT_APP_SITEKEY } = process.env;
+
+/**
+ *  SignUp UseerName popUp
+ * @component
+ * SignUp UseerName Differenet Components
+ * @returns {React.Component} - Main Body of SignUp UseerName PopUp
+ */
+function SignUpPopUpUserName({
+  setUserNamePage, email, userName, setUserName, password, setPassword, setCookies, removeCookie,
+}) {
+  // states
+  const [defaultUserNameValue, setdefaultUserNameValue] = useState(userName?.input);
+  const [defaultPasswordValue, setdefaultPasswordValue] = useState(password?.input);
+  const [verified, setVerified] = useState(false);
+  const [loading, setLoading] = useState(false);
+  const [buttonTxt, setButtonText] = useState('Sign up');
+  const [disabled, setDisabled] = useState(false);
+  const [redirectCaption, setRedirectCaption] = useState(false);
+  const [click, setClick] = useState(false);
+
+  // server generate Random Names
+  const generatedUsernames = generateRandomUsernamesServer(1, click);
+
+  // useContext
+  const {
+    // eslint-disable-next-line no-unused-vars
+    openSignUp, handleClose, handleClickOpenLogIn, handleClickOpenSignUp, openSignUpUsername, handleClickOpenSignUpUsername,
+  } = useContext(SignupContext);
+
+  const caption = (
+    <>
+      Reddit is anonymous, so your username is what
+      youโ€™ll go by here. Choose wiselyโ€”because once
+      you get a name, you canโ€™t change it.
+    </>
+
+  );
+
+  const refreshIcon = (
+    <InputAdornment
+      position="end"
+    >
+      <PublishedWithChangesIcon onClick={() => {
+        setClick(!click);
+        setUserName((prevState) => ({
+          ...prevState,
+          color: theme.palette.primary.main,
+          error: null,
+          input: generatedUsernames[0],
+        }));
+        setdefaultUserNameValue(generatedUsernames[0]);
+      }}
+      />
+    </InputAdornment>
+  );
+
+  // useEffect
+  useEffect(() => {
+    console.log(generatedUsernames);
+    if (generatedUsernames === null) {
+      return;
+    }
+    setUserName((prevState) => ({
+      ...prevState,
+      color: theme.palette.primary.main,
+      error: null,
+      input: generatedUsernames[0],
+    }));
+    setdefaultUserNameValue(generatedUsernames[0]);
+  }, [generatedUsernames]);
+
+  const signUpFunction = () => {
+    // console.log(userName);
+    checkUserNameSignUp(userName?.input, setUserName);
+    checkPassword(password?.input, setPassword, password);
+    signUp(email, userName, setUserName, password, setPassword, verified, setLoading, setButtonText, setDisabled, setRedirectCaption, setCookies, removeCookie, true, handleClose);
+  };
+  return (
+
+    <StyledDialog
+      data-testid="SignUpUserName-popup"
+      fullscreen
+      open={openSignUpUsername}
+      aria-labelledby="alert-dialog-title"
+      aria-describedby="alert-dialog-description"
+    >
+      <Box width="280px" height="454px">
+        <CloseIcon
+          sx={{
+            position: 'absolute', right: '16px', top: '16px', cursor: 'pointer',
+          }}
+          onClick={handleClose}
+        />
+        <ArrowBackIcon
+          sx={{
+            position: 'absolute', left: '16px', top: '16px', cursor: 'pointer',
+          }}
+          onClick={() => { if (disabled) return; setUserNamePage(false); handleClickOpenSignUp(); }}
+        />
+        <AuthenticationHeader reddit={false} title="Create your username and password" caption={caption} />
+
+        <RedditTextField
+          label="Username"
+          variant="filled"
+          required
+          InputProps={{
+            endAdornment: (
+              refreshIcon
+            ),
+            disableUnderline: true,
+          }}
+          clr={userName?.color}
+          onChange={(e) => {
+            setUserName((prevState) => ({
+              ...prevState,
+              input: e.target.value.trim(),
+            }));
+            checkUserNameSignUp(e.target.value.trim(), setUserName);
+            setdefaultUserNameValue(e.target.value.trim());
+          }}
+          helperText={userName.error}
+          value={defaultUserNameValue || ''}
+        />
+        <PasswordStrengthBar
+          password={password?.input}
+          minLength={4}
+          onChangeScore={(e) => (setPassword((prevState) => ({
+            ...prevState,
+            score: e,
+          })))}
+          scoreWords={[]}
+          shortScoreWord=""
+        />
+        <RedditTextField
+          label="Password"
+          variant="filled"
+          type="password"
+          required
+          InputProps={{
+            endAdornment: (
+              password.icon
+            ),
+            disableUnderline: true,
+          }}
+          clr={password?.color}
+          onChange={(e) => {
+            setPassword((prevState) => ({
+              ...prevState,
+              input: e.target.value.trim(),
+            }));
+            checkPassword(e.target.value.trim(), setPassword, undefined);
+            setdefaultPasswordValue(e.target.value.trim());
+          }}
+          value={defaultPasswordValue || ''}
+          helperText={password?.error}
+        />
+        <ReCAPTCHA
+          sitekey={REACT_APP_SITEKEY}
+          onExpired={() => setVerified(false)}
+          onChange={() => setVerified(true)}
+          size="normal"
+          sx={{ width: '320px' }}
+        />
+        <RedditLoadingButton
+          width="155px"
+          onClick={signUpFunction}
+          loading={loading}
+          disabled={disabled}
+          data-testid="sigup-btn-test"
+        >
+          {buttonTxt}
+        </RedditLoadingButton>
+
+        {redirectCaption
+          ? <Typography color="primary" fontSize="12px" fontFamily={fonts['system-ui']} fontWeight="600" margin="auto">You are now logged in. You will soon be redirected</Typography>
+          : null}
+
+      </Box>
+    </StyledDialog>
+  );
+}
+
+export default SignUpPopUpUserName;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainNavBar_SignNavbar_UserList_UserList.jsx.html b/docs/components_MainNavBar_SignNavbar_UserList_UserList.jsx.html new file mode 100644 index 00000000..a225af9f --- /dev/null +++ b/docs/components_MainNavBar_SignNavbar_UserList_UserList.jsx.html @@ -0,0 +1,102 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/UserList/UserList.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/UserList/UserList.jsx

+ + + + + + +
+
+
import React from 'react';
+import {
+  List, ListItemButton, ListItemIcon, ListItemText, Collapse, ClickAwayListener,
+} from '@mui/material';
+import ExpandMore from '@mui/icons-material/ExpandMore';
+import HelpOutlineOutlinedIcon from '@mui/icons-material/HelpOutlineOutlined';
+import LoginOutlinedIcon from '@mui/icons-material/LoginOutlined';
+import PersonOutlineOutlinedIcon from '@mui/icons-material/PersonOutlineOutlined';
+import StyledList from './styles';
+
+/**
+ * UserList
+ * @component
+ * @returns {React.Component} the User list which is the right lish in logged in navbar.
+ */
+function UserList({ logInPopup }) {
+  const [openHomeList, setOpenHomeList] = React.useState(0);
+  const handleClickHomeList = () => {
+    setOpenHomeList(!openHomeList);
+  };
+  return (
+    <ClickAwayListener onClickAway={() => { setOpenHomeList(false); }}>
+      <StyledList>
+        <ListItemButton onClick={handleClickHomeList} sx={{ display: 'flex' }}>
+          <ListItemIcon sx={{ display: 'contents' }}>
+            <PersonOutlineOutlinedIcon />
+          </ListItemIcon>
+          <ExpandMore sx={{ color: '#757575', fontSize: 20 }} />
+        </ListItemButton>
+        <Collapse in={Boolean(openHomeList)} timeout="auto" unmountOnExit>
+          <List component="div" disablePadding>
+            <ListItemButton>
+              <ListItemIcon>
+                <HelpOutlineOutlinedIcon />
+              </ListItemIcon>
+              <ListItemText primary="help center" />
+            </ListItemButton>
+            <ListItemButton onClick={logInPopup}>
+              <ListItemIcon>
+                <LoginOutlinedIcon />
+              </ListItemIcon>
+              <ListItemText primary="log in / sign up" />
+            </ListItemButton>
+          </List>
+        </Collapse>
+      </StyledList>
+    </ClickAwayListener>
+  );
+}
+
+export default UserList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git "a/docs/components_MainNavBar_SignNavbar_\331\220Authentication_FirstParty_FirstParty.jsx.html" "b/docs/components_MainNavBar_SignNavbar_\331\220Authentication_FirstParty_FirstParty.jsx.html" new file mode 100644 index 00000000..487fbed0 --- /dev/null +++ "b/docs/components_MainNavBar_SignNavbar_\331\220Authentication_FirstParty_FirstParty.jsx.html" @@ -0,0 +1,166 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/ูAuthentication/FirstParty/FirstParty.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/ูAuthentication/FirstParty/FirstParty.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+import { useCookies } from 'react-cookie';
+
+// mui components
+import { Typography } from '@mui/material';
+
+// styles
+import { FirstPartyContainer } from './styles';
+import { RedditLoadingButton, RedditTextField } from '../styles';
+import theme, { fonts } from '../../../../../styles/theme';
+
+// servers
+import { checkUserName, logIn } from '../../../../Authentication/FirstParty/firstpartyServer';
+
+/**
+ * Form for Logging in by username and passsword
+ *
+ * @component
+ * @returns {React.Component} First Party Form
+ */
+function FirstParty({ handleClose }) {
+  // useState
+  const [userName, setUserName] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+  const [password, setPassword] = useState({
+    input: '', color: theme.palette.neutral.main, icon: null, error: null,
+  });
+  const [buttonTxt, setButtonText] = useState('Log In');
+  const [loading, setLoading] = useState(false);
+  const [disabled, setDisabled] = useState(false);
+  const [redirectCaption, setRedirectCaption] = useState(false);
+
+  // useCookies
+  // eslint-disable-next-line no-unused-vars
+  const [cookies, setCookies, removeCookie] = useCookies(['redditUser']);
+  return (
+
+    <FirstPartyContainer
+      data-testid="FirstParty-test"
+      width="290px"
+      noValidate
+      onSubmit={(e) => {
+        logIn(
+          e,
+          setLoading,
+          userName,
+          password,
+          setPassword,
+          setButtonText,
+          setDisabled,
+          setRedirectCaption,
+          setCookies,
+          removeCookie,
+          setUserName,
+          true,
+          handleClose,
+        );
+      }}
+    >
+
+      <RedditTextField
+        data-testid="UserName-FirstParty-test"
+        label="Username"
+        variant="filled"
+        type="text"
+        required
+        InputProps={{
+          endAdornment: (
+            userName.icon
+          ),
+          disableUnderline: true,
+        }}
+        clr={userName.color}
+        onChange={(e) => {
+          setUserName((prevState) => ({
+            ...prevState,
+            input: e.target.value.trim(),
+          }));
+          checkUserName(e.target.value.trim(), setUserName);
+        }}
+        helperText={userName.error}
+      />
+      <RedditTextField
+        data-testid="Password-FirstParty-test"
+        label="Password"
+        variant="filled"
+        type="password"
+        required
+        InputProps={{
+          endAdornment: (
+            password.icon
+          ),
+          disableUnderline: true,
+        }}
+        clr={password.color}
+        onChange={(e) => setPassword((prevState) => ({
+          ...prevState,
+          input: e.target.value.trim(),
+        }))}
+      />
+
+      <RedditLoadingButton data-testid="login-btn-test" type="submit" loading={loading} disabled={disabled}>
+        {buttonTxt}
+      </RedditLoadingButton>
+
+      {redirectCaption
+        ? <Typography color="primary" fontSize="12px" fontFamily={fonts['system-ui']} fontWeight="600" margin="10px 0px">You are now logged in. You will soon be redirected</Typography>
+        : null}
+    </FirstPartyContainer>
+
+  );
+}
+
+export default FirstParty;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git "a/docs/components_MainNavBar_SignNavbar_\331\220Authentication_SignUpEmail_SignUpEmail.jsx.html" "b/docs/components_MainNavBar_SignNavbar_\331\220Authentication_SignUpEmail_SignUpEmail.jsx.html" new file mode 100644 index 00000000..db9262bb --- /dev/null +++ "b/docs/components_MainNavBar_SignNavbar_\331\220Authentication_SignUpEmail_SignUpEmail.jsx.html" @@ -0,0 +1,124 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/ูAuthentication/SignUpEmail/SignUpEmail.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/ูAuthentication/SignUpEmail/SignUpEmail.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+
+// mui compoenets
+import { Typography } from '@mui/material';
+
+// components
+import AuthenticationHeader from '../../../../Authentication/AuthenticationHeader/AuthenticationHeader';
+import ThirdParty from '../ThirdParty/ThirdParty';
+import Divider from '../../../../Authentication/Divider/Divider';
+import Email from '../Email/Email';
+
+// styles
+import { StyledLink } from '../../../../Authentication/styles';
+
+/**
+ * SignUp Email Componenet
+ * @returns {React.Component}
+ */
+function SignUpEmail({ setUserNamePage, email, setEmail }) {
+  const [loading, setLoading] = useState(false);
+
+  const continueEmail = () => {
+    // console.log(email);// true value but case no change wrong value
+    setLoading(true);
+    // Has error (syntax error Email or empty Email)
+    if (email.error !== null) {
+      setLoading(false);
+      return;
+    }
+    // check if Empty (case he didn't make any change in the input field)
+    if (email.input === '') {
+      setLoading(false);
+      return;
+    }
+
+    // Email is Accepted
+    setTimeout(() => {
+      setLoading(false);
+      setUserNamePage(true);
+    }, 500);
+  };
+
+  const caption = (
+    <>
+      By continuing, you are setting up a Reddit account and agree to our
+      {' '}
+      <StyledLink fontWeight="400" href="https://www.redditinc.com/policies/user-agreement" capital="none">User Agreement</StyledLink>
+      {' '}
+      and
+      {' '}
+      <StyledLink fontWeight="400" href="https://www.reddit.com/policies/privacy-policy" capital="none">Privacy Policy </StyledLink>
+      .
+    </>
+  );
+
+  return (
+    <>
+      <AuthenticationHeader reddit={false} title="Sign up" caption={caption} />
+      <ThirdParty circular={false} />
+
+      <Divider />
+
+      <Email email={email} setEmail={setEmail} ispopup="false" onSubmitFn={continueEmail} loading={loading} width="280px" buttonText="continue" fieldText="Email" recaptcha={false} setVerified={null} disabled={false} />
+
+      <Typography paragraph fontSize={12}>
+        Already a redditor?
+        {' '}
+        <StyledLink href="/login" fontWeight="600" capital="uppercase">log in</StyledLink>
+      </Typography>
+    </>
+  );
+}
+export default SignUpEmail;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git "a/docs/components_MainNavBar_SignNavbar_\331\220Authentication_ThirdParty_ThirdPartyButton_ThirdPartyButton.jsx.html" "b/docs/components_MainNavBar_SignNavbar_\331\220Authentication_ThirdParty_ThirdPartyButton_ThirdPartyButton.jsx.html" new file mode 100644 index 00000000..f6a36ce5 --- /dev/null +++ "b/docs/components_MainNavBar_SignNavbar_\331\220Authentication_ThirdParty_ThirdPartyButton_ThirdPartyButton.jsx.html" @@ -0,0 +1,69 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/ูAuthentication/ThirdParty/ThirdPartyButton/ThirdPartyButton.jsx + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/ูAuthentication/ThirdParty/ThirdPartyButton/ThirdPartyButton.jsx

+ + + + + + +
+
+
import { ThirdPartyBtn, ButtonIcon } from './styles';
+
+/**
+ * Third Party Button
+ * @returns {React.Component} -Third Party Button Styled
+ */
+function ThirdPartyButton({
+  img, alt, txt, onClick,
+}) {
+  return (
+    <ThirdPartyBtn variant="outlined" onClick={onClick}>
+      <ButtonIcon src={img} alt={alt} />
+      {txt}
+    </ThirdPartyBtn>
+  );
+}
+
+export default ThirdPartyButton;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git "a/docs/components_MainNavBar_SignNavbar_\331\220Authentication_ThirdParty_styles.js.html" "b/docs/components_MainNavBar_SignNavbar_\331\220Authentication_ThirdParty_styles.js.html" new file mode 100644 index 00000000..f9c2f4dd --- /dev/null +++ "b/docs/components_MainNavBar_SignNavbar_\331\220Authentication_ThirdParty_styles.js.html" @@ -0,0 +1,62 @@ + + + + + JSDoc: Source: components/MainNavBar/SignNavbar/ูAuthentication/ThirdParty/styles.js + + + + + + + + + + +
+ +

Source: components/MainNavBar/SignNavbar/ูAuthentication/ThirdParty/styles.js

+ + + + + + +
+
+
/* eslint-disable import/prefer-default-export */
+import { Box } from '@mui/material';
+import { styled } from '@mui/material/styles';
+
+/**
+ * Box for Third Part Button
+ */
+export const ThirdPartyContainer = styled(Box)(({ width }) => ({
+  width: `${width}`,
+  margin: '15px 0px',
+}));
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Comments_Comments.jsx.html b/docs/components_MainProfile_Comments_Comments.jsx.html new file mode 100644 index 00000000..94337687 --- /dev/null +++ b/docs/components_MainProfile_Comments_Comments.jsx.html @@ -0,0 +1,112 @@ + + + + + JSDoc: Source: components/MainProfile/Comments/Comments.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Comments/Comments.jsx

+ + + + + + +
+
+
import { Divider } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import { useEffect, useContext, useState } from 'react';
+import { PostsQueueBox } from './styles';
+import CommentsContent from './CommentsContent/CommentsContent';
+import CommentsHeader from './CommentsHeader/CommentsHeader';
+import { CommunitiesContext } from '../../../contexts/CommunitiesModeratorContext';
+
+/**
+ * Content component represents an entity of a comment
+ *
+ * @component Comments
+ * @property {object} comment - conatin all info needed to be shown in the comment
+ * @returns {React.Component} Comments
+ */
+
+function Comments(props) {
+  const {
+    entity, profile, noheader, overview,
+  } = props;
+  const { username } = useParams();
+  const { communities } = useContext(CommunitiesContext);
+  const [modList, setModList] = useState(false);
+
+  useEffect(() => {
+    console.log(entity);
+    if (entity?.ownerType === 'Subreddit' && communities?.filter((element) => element.fixedName === entity?.owner.name).length > 0) {
+      setModList(true);
+    }
+  }, [communities]);
+
+  return (
+    <PostsQueueBox>
+      <CommentsHeader
+        post={entity}
+        noheader={noheader}
+      />
+      <Divider variant="middle" />
+      { entity?.comments?.map((comment, index) => (
+        <>
+          <CommentsContent
+            key={`${index + 0}`}
+            postid={entity?._id}
+            comment={comment}
+            op={entity?.author?.name === username}
+            modList={modList}
+            profile={profile}
+            overview={overview}
+            ownerType={entity?.ownerType}
+            owner={entity?.owner.name}
+          />
+          <Divider variant="middle" />
+        </>
+      ))}
+
+    </PostsQueueBox>
+
+  );
+}
+
+export default Comments;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Comments_CommentsContent_CommentsContent.jsx.html b/docs/components_MainProfile_Comments_CommentsContent_CommentsContent.jsx.html new file mode 100644 index 00000000..649d2aa9 --- /dev/null +++ b/docs/components_MainProfile_Comments_CommentsContent_CommentsContent.jsx.html @@ -0,0 +1,351 @@ + + + + + JSDoc: Source: components/MainProfile/Comments/CommentsContent/CommentsContent.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Comments/CommentsContent/CommentsContent.jsx

+ + + + + + +
+
+
import {
+  Box, Divider, Menu, MenuItem,
+} from '@mui/material';
+import MoreHorizOutlinedIcon from '@mui/icons-material/MoreHorizOutlined';
+import { useContext, useState } from 'react';
+import moment from 'moment/moment';
+import DeleteOutlineOutlinedIcon from '@mui/icons-material/DeleteOutlineOutlined';
+import BookmarkBorderOutlinedIcon from '@mui/icons-material/BookmarkBorderOutlined';
+import ModeEditOutlinedIcon from '@mui/icons-material/ModeEditOutlined';
+import BookmarksOutlinedIcon from '@mui/icons-material/BookmarksOutlined';
+import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined';
+import BlockOutlinedIcon from '@mui/icons-material/BlockOutlined';
+import LockIcon from '@mui/icons-material/Lock';
+import Inventory2Icon from '@mui/icons-material/Inventory2';
+import DoDisturbAltIcon from '@mui/icons-material/DoDisturbAlt';
+import CheckCircleIcon from '@mui/icons-material/CheckCircle';
+import CancelPresentationOutlinedIcon from '@mui/icons-material/CancelPresentationOutlined';
+import { useNavigate } from 'react-router-dom';
+import { useEditPostContext } from '../../../../contexts/EditPostContext';
+import { UserContext } from '../../../../contexts/UserProvider';
+
+import { CommentText } from '../styles';
+import {
+  CommentsBoxBlue, CommentsBoxContent, DashedLine, FooterText, ModList, MoreList, ResDivider, SelectItem,
+} from './styles';
+import { actionComment, actionCommentModerate, deletePostComment } from '../../profileServer';
+
+/**
+ * the Body of an comment
+ *
+ * @component CommentsContent
+ * @property {string} points - number of points the comment did get
+ * @property {string} time - time of creating the comment
+ * @property {string} body - the body paragraph of the comment
+ * @returns {React.Component} CommentsContent
+ */
+
+function CommentsContent(props) {
+  const {
+    comment, op, modList, overview, profile, ownerType, owner, postid,
+  } = props;
+  const { username } = useContext(UserContext);
+  const [saved, setSaved] = useState(comment.isSaved);
+  const [locked, setLocked] = useState(comment.locked);
+  const [modState, setModState] = useState(comment.modState);
+
+  const [anchorEl, setAnchorEl] = useState(null);
+  const open = Boolean(anchorEl);
+  const handleClick = (event) => {
+    setAnchorEl(event.currentTarget);
+  };
+  const handleClose = () => {
+    setAnchorEl(null);
+  };
+  // switch icon to saved post and vice versa
+  const handleSave = () => {
+    actionComment(comment._id, saved ? 'unsave' : 'save');
+    setSaved((prev) => !prev);
+  };
+
+  const handleLock = () => {
+    actionComment(comment._id, locked ? 'unlock_comments' : 'lock_comments');
+    setLocked((prev) => !prev);
+  };
+
+  const handleSpam = () => {
+    actionCommentModerate(comment._id, 'spam');
+    setModState('spammed');
+  };
+
+  const handleApprove = () => {
+    actionCommentModerate(comment._id, 'approve');
+    setModState('approved');
+  };
+
+  const handleRemove = () => {
+    actionCommentModerate(comment._id, 'remove');
+    setModState('removed');
+  };
+
+  const handleDelete = () => {
+    deletePostComment('comments', comment._id);
+  };
+
+  const navigate = useNavigate();
+  const { setEditPost } = useEditPostContext();
+
+  return (
+    <CommentsBoxContent>
+
+      <DashedLine />
+      {comment.parentType !== 'Post' ? <DashedLine /> : null}
+      <CommentsBoxBlue overview={overview}>
+        <Box sx={{ display: 'flex', alignItems: 'center', width: '100%' }} onClick={() => { setEditPost(false); navigate(`/${ownerType === 'Subreddit' ? 'subreddit' : 'user'}/${owner}/comments/${postid}`); }}>
+          <CommentText variant="caption" coloring="black">
+            {username}
+            {' '}
+          </CommentText>
+          {op && (
+          <CommentText variant="caption" coloring="#0079d3" sx={{ fontWeight: 700 }}>
+            OP
+            {' '}
+          </CommentText>
+          )}
+          <CommentText variant="caption" coloring="#787c7e">
+            {comment.votes}
+            {' '}
+            point .
+            {' '}
+            {(moment.utc(comment.createdAt).local().startOf('seconds')
+              .fromNow())}
+          </CommentText>
+          {locked && <LockIcon sx={{ color: '#ffd635', marginLeft: '3px' }} fontSize="caption" />}
+          {modState === 'spammed' && <Inventory2Icon sx={{ color: '#ff585b', marginLeft: '3px' }} fontSize="caption" />}
+          {modState === 'approved' && <CheckCircleIcon sx={{ color: '#75d377', marginLeft: '3px' }} fontSize="caption" />}
+          {modState === 'removed' && <DoDisturbAltIcon sx={{ color: '#ff585b', marginLeft: '3px' }} fontSize="caption" />}
+        </Box>
+        <Box onClick={() => { setEditPost(false); navigate(`/${ownerType === 'Subreddit' ? 'r' : 'user'}/${owner}/comments/${postid}`); }} sx={{ width: '100%' }}>
+          <CommentText variant="body2" coloring="black">{comment.text}</CommentText>
+        </Box>
+        <Box sx={{ display: 'flex', alignItems: 'center', height: '24px' }}>
+          <CommentText variant="caption" coloring="#787c7e" hover="true" sx={{ fontWeight: 700 }}>Reply</CommentText>
+
+          <MoreList onClick={handleClick}>
+            <MoreHorizOutlinedIcon />
+          </MoreList>
+          <Menu
+            id="long-menu"
+            MenuListProps={{
+              'aria-labelledby': 'long-button',
+            }}
+            anchorEl={anchorEl}
+            open={open}
+            onClose={handleClose}
+            PaperProps={{
+              style: {
+                width: '150px',
+                padding: 0,
+              },
+            }}
+            sx={{ '& .MuiButtonBase-root': { padding: '0px 3px' } }}
+          >
+
+            <MenuItem onClick={() => { handleSave(); handleClose(); }}>
+              {!saved ? (
+                <SelectItem>
+                  <BookmarkBorderOutlinedIcon sx={{ marginRight: 1 }} />
+                  Save
+                </SelectItem>
+              )
+                : (
+                  <SelectItem condition={true.toString()}>
+                    <BookmarksOutlinedIcon sx={{ marginRight: 1 }} />
+                    Unsave
+                  </SelectItem>
+                )}
+            </MenuItem>
+            {(modList && !profile) && (
+            <>
+              <Divider />
+              <ModList responsive3icons={true.toString()}>
+
+                <MenuItem onClick={() => { handleClose(); handleApprove(); }}>
+
+                  <SelectItem>
+                    <CheckCircleOutlineOutlinedIcon sx={{ marginRight: 1 }} />
+                    Approve
+                  </SelectItem>
+
+                </MenuItem>
+                <Divider />
+
+                <MenuItem onClick={() => { handleClose(); handleRemove(); }}>
+
+                  <SelectItem>
+                    <BlockOutlinedIcon sx={{ marginRight: 1 }} />
+                    Removed
+                  </SelectItem>
+
+                </MenuItem>
+                <Divider />
+                <MenuItem onClick={() => { handleClose(); handleSpam(); }}>
+
+                  <SelectItem>
+                    <CancelPresentationOutlinedIcon sx={{ marginRight: 1 }} />
+                    Spam
+                  </SelectItem>
+
+                </MenuItem>
+                <Divider />
+                <MenuItem onClick={() => { handleClose(); handleLock(); }}>
+
+                  <SelectItem>
+                    <LockIcon sx={{ marginRight: 1 }} />
+                    {locked ? 'Unlock' : 'Lock'}
+                  </SelectItem>
+
+                </MenuItem>
+              </ModList>
+            </>
+            )}
+
+            {profile && (
+            <>
+              <Divider />
+
+              <MenuItem onClick={() => { handleClose(); setEditPost(true); navigate(`/${ownerType === 'Subreddit' ? 'r' : 'user'}/${owner}/comments/${postid}`); }}>
+                <SelectItem>
+                  <ModeEditOutlinedIcon sx={{ marginRight: 1 }} />
+                  Edit Post
+                </SelectItem>
+
+              </MenuItem>
+              <Divider />
+
+              <MenuItem onClick={() => { handleDelete(); handleClose(); }}>
+
+                <SelectItem>
+                  <DeleteOutlineOutlinedIcon sx={{ marginRight: 1 }} />
+                  Delete
+                </SelectItem>
+
+              </MenuItem>
+
+              {modList && (
+              <ModList responsive3icons={true.toString()}>
+                <Divider />
+                <MenuItem onClick={() => { handleClose(); handleApprove(); }}>
+
+                  <SelectItem>
+                    <CheckCircleOutlineOutlinedIcon sx={{ marginRight: 1 }} />
+                    Approve
+                  </SelectItem>
+
+                </MenuItem>
+                <Divider />
+
+                <MenuItem onClick={() => { handleClose(); handleRemove(); }}>
+
+                  <SelectItem>
+                    <BlockOutlinedIcon sx={{ marginRight: 1 }} />
+                    Removed
+                  </SelectItem>
+
+                </MenuItem>
+                <Divider />
+                <MenuItem onClick={() => { handleClose(); handleSpam(); }}>
+
+                  <SelectItem>
+                    <CancelPresentationOutlinedIcon sx={{ marginRight: 1 }} />
+                    Spam
+                  </SelectItem>
+
+                </MenuItem>
+                <Divider />
+                <MenuItem onClick={() => { handleClose(); handleLock(); }}>
+
+                  <SelectItem>
+                    <LockIcon sx={{ marginRight: 1 }} />
+                    {locked ? 'Unlock' : 'Lock'}
+                  </SelectItem>
+
+                </MenuItem>
+              </ModList>
+              )}
+            </>
+            )}
+
+          </Menu>
+
+          {modList && (
+          <>
+            <ResDivider responsive3icons={true.toString()} orientation="vertical" />
+            <MoreList responsive3icons={true.toString()} onClick={handleApprove}>
+              <CheckCircleOutlineOutlinedIcon fontSize="small" />
+              <FooterText variant="caption">Approve</FooterText>
+            </MoreList>
+            <MoreList responsive3icons={true.toString()} onClick={handleRemove}>
+              <BlockOutlinedIcon fontSize="small" />
+              <FooterText variant="caption">Removed</FooterText>
+            </MoreList>
+            <MoreList responsive3icons={true.toString()} onClick={handleSpam}>
+              <CancelPresentationOutlinedIcon fontSize="small" />
+              <FooterText variant="caption">Spam</FooterText>
+            </MoreList>
+            <MoreList responsive3icons={true.toString()} onClick={handleLock}>
+              <LockIcon fontSize="small" />
+              <FooterText variant="caption">
+                {locked ? 'Unlock' : 'Lock'}
+              </FooterText>
+            </MoreList>
+          </>
+          )}
+        </Box>
+      </CommentsBoxBlue>
+    </CommentsBoxContent>
+  );
+}
+
+export default CommentsContent;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Comments_CommentsHeader_CommentsHeader.jsx.html b/docs/components_MainProfile_Comments_CommentsHeader_CommentsHeader.jsx.html new file mode 100644 index 00000000..f8a35189 --- /dev/null +++ b/docs/components_MainProfile_Comments_CommentsHeader_CommentsHeader.jsx.html @@ -0,0 +1,130 @@ + + + + + JSDoc: Source: components/MainProfile/Comments/CommentsHeader/CommentsHeader.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Comments/CommentsHeader/CommentsHeader.jsx

+ + + + + + +
+
+
import ChatBubbleOutlineOutlinedIcon from '@mui/icons-material/ChatBubbleOutlineOutlined';
+import { useContext } from 'react';
+import { UserContext } from '../../../../contexts/UserProvider';
+
+import { CommentText } from '../styles';
+import { CommentsBoxHeader, Flair, TagPost } from './styles';
+
+/**
+ * Header of the comment
+ *
+ * @component CommentsHeader
+ * @param {string} username - name of the currently loggedin user.
+ * @property {string} subReddit -name of the subreddit in which is the comment.
+ * @property {string} publisher -author of the comment.
+ * @property {string} title -the title of a comment.
+ * @returns {React.Component} CommentsHeader
+ */
+
+function CommentsHeader(props) {
+  const { username } = useContext(UserContext);
+  const {
+    post, noheader,
+  } = props;
+  return (
+    <CommentsBoxHeader noheader={noheader}>
+      <ChatBubbleOutlineOutlinedIcon sx={{ marginRight: 1 }} />
+      <CommentText
+        variant="caption"
+        hover="true"
+        onClick={() => { window.location.pathname = `./user/${username}`; }}
+      >
+        {username}
+
+      </CommentText>
+      <CommentText variant="caption" coloring="#787c7e">
+        commented on
+        {' '}
+        {post?.title}
+        .
+      </CommentText>
+      {post?.spoiler && <TagPost color="#A4A7A8" variant="caption">spoiler</TagPost>}
+      {/* check with baaaaaack */}
+      {post?.nsfw && <TagPost color="#FF585B" variant="caption">nsfw</TagPost>}
+      {
+            post?.flairId?.text
+            && (
+            <Flair
+              disableripple
+              backgroundcolor={post?.flairId?.backgroundColor}
+              flaircolor={post?.flairId?.textColor}
+            >
+              {post?.flairId?.text}
+            </Flair>
+            )
+          }
+      <CommentText
+        variant="caption"
+        coloring="black"
+        hover="true"
+        sx={{ fontWeight: 700 }}
+        onClick={() => { window.location.pathname = (post?.ownerType === 'User') ? `./user/${post?.owner?.name}` : `./Subreddit/${post?.owner?.name}`; }}
+      >
+        {post?.ownerType === 'User' ? 'u/' : 'r/'}
+        {post?.owner?.name}
+        .
+      </CommentText>
+      <CommentText variant="caption" coloring="#787c7e">
+        Posted by
+      </CommentText>
+      <CommentText variant="caption" coloring="#787c7e" hover="true" onClick={() => { window.location.pathname = `./user/${post?.author?.name}`; }}>
+        u/
+        {post?.author?.name}
+      </CommentText>
+    </CommentsBoxHeader>
+
+  );
+}
+
+export default CommentsHeader;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_EmptyContent_EmptyContent.jsx.html b/docs/components_MainProfile_EmptyContent_EmptyContent.jsx.html new file mode 100644 index 00000000..18f0a57c --- /dev/null +++ b/docs/components_MainProfile_EmptyContent_EmptyContent.jsx.html @@ -0,0 +1,104 @@ + + + + + JSDoc: Source: components/MainProfile/EmptyContent/EmptyContent.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/EmptyContent/EmptyContent.jsx

+ + + + + + +
+
+
import {
+  EmptyContentBox, DownArrow, UpArrow, SpecialBox, ArrowBox, EmptyText,
+} from './styles';
+/**
+ * the empty content when your having no posts nor comments
+ *
+ * @component EmptyContent
+ * @property {string} emptyContent - the string that should appear in the empty page
+ * @returns {React.Component} EmptyContent
+ */
+function EmptyContent(props) {
+  const { emptyContent } = props;
+  return (
+    <>
+      <EmptyContentBox>
+        <UpArrow color="disabled" />
+        <DownArrow color="disabled" />
+      </EmptyContentBox>
+      <EmptyContentBox>
+        <UpArrow color="disabled" />
+        <DownArrow color="disabled" />
+      </EmptyContentBox>
+      <EmptyContentBox>
+        <UpArrow color="disabled" />
+        <DownArrow color="disabled" />
+      </EmptyContentBox>
+      <SpecialBox>
+        <ArrowBox>
+          <UpArrow color="disabled" />
+          <DownArrow color="disabled" />
+        </ArrowBox>
+        <EmptyText>
+          {emptyContent}
+        </EmptyText>
+      </SpecialBox>
+      <EmptyContentBox>
+        <UpArrow color="disabled" />
+        <DownArrow color="disabled" />
+      </EmptyContentBox>
+      <EmptyContentBox>
+        <UpArrow color="disabled" />
+        <DownArrow color="disabled" />
+      </EmptyContentBox>
+      <EmptyContentBox>
+        <UpArrow color="disabled" />
+        <DownArrow color="disabled" />
+      </EmptyContentBox>
+
+    </>
+  );
+}
+
+export default EmptyContent;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_ModeratorList_ModeratorList.jsx.html b/docs/components_MainProfile_ModeratorList_ModeratorList.jsx.html new file mode 100644 index 00000000..39cc5d9a --- /dev/null +++ b/docs/components_MainProfile_ModeratorList_ModeratorList.jsx.html @@ -0,0 +1,146 @@ + + + + + JSDoc: Source: components/MainProfile/ModeratorList/ModeratorList.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/ModeratorList/ModeratorList.jsx

+ + + + + + +
+
+
import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined';
+import BlockOutlinedIcon from '@mui/icons-material/BlockOutlined';
+import CancelPresentationOutlinedIcon from '@mui/icons-material/CancelPresentationOutlined';
+import CheckBoxIcon from '@mui/icons-material/CheckBox';
+import CropSquareOutlinedIcon from '@mui/icons-material/CropSquareOutlined';
+import { Divider } from '@mui/material';
+import { DividerRes, SelectBox, SelectItem } from './styles';
+
+/**
+ * list of the functionality of the moderator for smaller screens
+ *
+ * @component ModeratorList
+ * @returns {React.Component} ModeratorList
+ */
+function ModeratorList({
+  nsfw,
+  spoiler,
+  locked,
+  handleLock,
+  handleSpoiler,
+  handleNsfw,
+  handleApprove,
+  handleRemove,
+  handleSpam,
+}) {
+  return (
+    <SelectBox>
+      <SelectItem responsive={true.toString()} onClick={handleApprove}>
+        <CheckCircleOutlineOutlinedIcon sx={{ marginRight: 1 }} />
+        Approve
+      </SelectItem>
+      <DividerRes />
+      <SelectItem responsive={true.toString()} onClick={handleRemove}>
+        <BlockOutlinedIcon sx={{ marginRight: 1 }} />
+        Remove
+      </SelectItem>
+      <DividerRes />
+      <SelectItem responsive={true.toString()} onClick={handleSpam}>
+        <CancelPresentationOutlinedIcon sx={{ marginRight: 1 }} />
+        Spam
+      </SelectItem>
+      <DividerRes />
+      <SelectItem>
+        <CropSquareOutlinedIcon sx={{ marginRight: 1 }} />
+        Distinguish As Mod
+      </SelectItem>
+      <Divider />
+      {!locked ? (
+        <SelectItem onClick={() => { handleLock(); }}>
+          <CropSquareOutlinedIcon sx={{ marginRight: 1 }} />
+          Lock Comments
+        </SelectItem>
+      )
+        : (
+          <SelectItem onClick={() => { handleLock(); }}>
+            <CheckBoxIcon sx={{ marginRight: 1 }} />
+            Lock Comments
+          </SelectItem>
+        )}
+      <Divider />
+      <SelectItem>
+        <CropSquareOutlinedIcon sx={{ marginRight: 1 }} />
+        Mark As OC
+      </SelectItem>
+      <Divider />
+      {!spoiler ? (
+        <SelectItem onClick={() => { handleSpoiler(); }}>
+          <CropSquareOutlinedIcon sx={{ marginRight: 1 }} />
+          Mark As Spoiler
+        </SelectItem>
+      )
+        : (
+          <SelectItem onClick={() => { handleSpoiler(); }}>
+            <CheckBoxIcon sx={{ marginRight: 1 }} />
+            Mark As Spoiler
+          </SelectItem>
+        )}
+      <Divider />
+      {!nsfw ? (
+        <SelectItem onClick={() => { handleNsfw(); }}>
+          <CropSquareOutlinedIcon sx={{ marginRight: 1 }} />
+          Mark As NSFW
+        </SelectItem>
+      )
+        : (
+          <SelectItem onClick={() => { handleNsfw(); }}>
+            <CheckBoxIcon sx={{ marginRight: 1 }} />
+            Mark As NSFW
+          </SelectItem>
+        )}
+    </SelectBox>
+  );
+}
+
+export default ModeratorList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherHeader_OtherProfileHeader.jsx.html b/docs/components_MainProfile_OtherProfile_OtherHeader_OtherProfileHeader.jsx.html new file mode 100644 index 00000000..0cadd4de --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherHeader_OtherProfileHeader.jsx.html @@ -0,0 +1,154 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherHeader/OtherProfileHeader.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherHeader/OtherProfileHeader.jsx

+ + + + + + +
+
+
import { ClickAwayListener } from '@mui/material';
+import Box from '@mui/material/Box';
+import { useState } from 'react';
+import { useNavigate, useParams } from 'react-router-dom';
+import MoreHorizOutlinedIcon from '@mui/icons-material/MoreHorizOutlined';
+import {
+  PageHeader, HeaderBox, HeaderButton, SelectBox, SelectItem,
+} from './styles';
+
+/**
+ * OtherProfileHeader
+ * @component
+ * @property  {function} handleClick to navigate to the subpage
+ * @return {React.Component} - OtherProfileHeader
+ */
+
+function OtherProfileHeader() {
+  const { subTitle, username } = useParams();
+  const navigate = useNavigate();
+
+  /**
+   * this function to navigate between the taps
+   * @param {string} subPage - the page to navigate to
+   */
+  const handleClick = (subPage) => {
+    navigate(`/user/${username}/${subPage}`);
+  };
+
+  const [showList, setShowList] = useState(false);
+
+  const handleShowList = () => {
+    setShowList((prev) => !prev);
+  };
+
+  const handleClickAway = () => {
+    setShowList(false);
+  };
+
+  const content = [
+    {
+      id: 1, Title: 'Comments', text: 'comments', res: 'res6',
+    },
+  ];
+
+  return (
+    <Box sx={{ flexGrow: 1 }}>
+      <PageHeader position="static">
+        <HeaderBox subtitle={subTitle}>
+          <HeaderButton
+            color="inherit"
+            onClick={() => { handleClick(''); }}
+            condition={(subTitle === undefined || subTitle.includes('sort')).toString()}
+          >
+            overview
+
+          </HeaderButton>
+          <HeaderButton
+            color="inherit"
+            onClick={() => { handleClick('submitted'); }}
+            condition={(subTitle === 'submitted').toString()}
+            data-testid="posts-tap"
+          >
+            posts
+          </HeaderButton>
+          {content.map((entity) => (
+            <HeaderButton
+              color="inherit"
+              key={entity.id}
+              onClick={() => { handleClick(`${entity.text}`); }}
+              condition={(subTitle === entity.text).toString()}
+              responsive={entity.res}
+            >
+              {entity.Title}
+            </HeaderButton>
+          ))}
+          <ClickAwayListener onClickAway={handleClickAway}>
+            <HeaderButton removedots="true">
+              <MoreHorizOutlinedIcon onClick={handleShowList} color="action" />
+              {showList && (
+
+              <SelectBox>
+                {content.map((entity) => (
+                  <SelectItem
+                    onClick={() => { handleClick(`${entity.text}`); }}
+                    responsive={entity.res}
+                    key={entity.id}
+                  >
+                    {entity.Title}
+                  </SelectItem>
+                ))}
+              </SelectBox>
+
+              )}
+            </HeaderButton>
+          </ClickAwayListener>
+
+        </HeaderBox>
+      </PageHeader>
+    </Box>
+  );
+}
+
+export default OtherProfileHeader;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileContent_OtherProfileContent.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileContent_OtherProfileContent.jsx.html new file mode 100644 index 00000000..c96aaae7 --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileContent_OtherProfileContent.jsx.html @@ -0,0 +1,115 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/OtherProfileContent.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/OtherProfileContent.jsx

+ + + + + + +
+
+
import { useEffect, useState, useMemo } from 'react';
+import { useLocation, useParams } from 'react-router-dom';
+// import InfiniteScroll from 'react-infinite-scroll-component';
+import { overviewServer } from '../../../profileServer';
+import EmptyContent from '../OtherProfileEmptyContent/OtherProfileEmptyContent';
+import Filter from '../OtherProfileFilter/OtherProfileFilter';
+import ContentBox from './styles';
+import Posts from '../../../Posts/Posts';
+import Comments from '../../../Comments/Comments';
+import mergeTwo from '../../../../../utils/mergeSort';
+// import { useListingContext } from '../../../../../contexts/ListingContext';
+
+function useQuery() {
+  const { search } = useLocation();
+
+  return useMemo(() => new URLSearchParams(search), [search]);
+}
+
+/**
+ * Content component display the comments and posts in the profile page
+ *
+ * @component OtherProfileContent
+ * @property {array} posts -array of posts objects
+ * @property {array} comments -array of comments objects
+ * @property {string} username
+ * @returns {React.Component} OtherProfileContent
+ */
+function OtherProfileContent() {
+  const { username } = useParams();
+  const [isContent, setIsContent] = useState(false);
+  const query = useQuery();
+  const sort = query.get('sort');
+  const [posts, comments] = overviewServer(username, sort);
+
+  // const { setPage } = useListingContext();
+  // const fetchMoreData = () => {
+  //   setPage((page) => page + 1);
+  // };
+
+  useEffect(() => {
+    setIsContent(false);
+    if (posts?.length > 0 || comments?.length > 0) { setIsContent(true); } else { setIsContent(false); }
+  }, [username, posts, comments, sort]);
+
+  const emptyContent = `hmm... u/${username}
+          hasn't posted recently`;
+
+  return (
+    <ContentBox>
+      <Filter subTitle2="./" />
+      {!isContent && <EmptyContent emptyContent={emptyContent} />}
+      {isContent
+          && (
+            mergeTwo(posts, comments, sort).map((entity, index) => (
+              (!entity.comments) ? <Posts key={`${index + 0}`} post={entity} condition="true" />
+                : (entity.author.name === username) ? <Posts key={`${index + 0}`} post={entity} condition="false" />
+                  : <Comments key={`${index + 0}`} entity={entity} overview="true" profile={false} />
+            ))
+          )}
+    </ContentBox>
+  );
+}
+
+export default OtherProfileContent;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileEmptyContent_OtherProfileEmptyContent.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileEmptyContent_OtherProfileEmptyContent.jsx.html new file mode 100644 index 00000000..aad75029 --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileEmptyContent_OtherProfileEmptyContent.jsx.html @@ -0,0 +1,105 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileEmptyContent/OtherProfileEmptyContent.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileEmptyContent/OtherProfileEmptyContent.jsx

+ + + + + + +
+
+
import {
+  EmptyContentBox, DownArrow, UpArrow, SpecialBox, ArrowBox, EmptyText,
+} from './styles';
+
+/**
+ * the empty content when your having no posts nor comments
+ *
+ * @component OtherProfileEmptyContent
+ * @property {string} emptyContent - the string that should appear in the empty page
+ * @returns {React.Component} OtherProfileEmptyContent
+ */
+function OtherProfileEmptyContent(props) {
+  const { emptyContent } = props;
+  return (
+    <>
+      <EmptyContentBox>
+        <UpArrow color="disabled" />
+        <DownArrow color="disabled" />
+      </EmptyContentBox>
+      <EmptyContentBox>
+        <UpArrow color="disabled" />
+        <DownArrow color="disabled" />
+      </EmptyContentBox>
+      <EmptyContentBox>
+        <UpArrow color="disabled" />
+        <DownArrow color="disabled" />
+      </EmptyContentBox>
+      <SpecialBox>
+        <ArrowBox>
+          <UpArrow color="disabled" />
+          <DownArrow color="disabled" />
+        </ArrowBox>
+        <EmptyText>
+          {emptyContent}
+        </EmptyText>
+      </SpecialBox>
+      <EmptyContentBox>
+        <UpArrow color="disabled" />
+        <DownArrow color="disabled" />
+      </EmptyContentBox>
+      <EmptyContentBox>
+        <UpArrow color="disabled" />
+        <DownArrow color="disabled" />
+      </EmptyContentBox>
+      <EmptyContentBox>
+        <UpArrow color="disabled" />
+        <DownArrow color="disabled" />
+      </EmptyContentBox>
+
+    </>
+  );
+}
+
+export default OtherProfileEmptyContent;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileFilter_OtherProfileFilter.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileFilter_OtherProfileFilter.jsx.html new file mode 100644 index 00000000..2cb180ba --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileFilter_OtherProfileFilter.jsx.html @@ -0,0 +1,73 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilter.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilter.jsx

+ + + + + + +
+
+
import OtherProfileFilterFull from './OtherProfileFilterFull/OtherProfileFilterFull';
+import OtherProfileFilterSmall from './OtherProfileFilterSmall/OtherProfileFilterSmall';
+import { FilterBox } from './styles';
+
+/**
+ * Navbar to filter posts by their category
+ *
+ * @component OtherProfileFilter
+ * @property {string} subTitle - title of page should navigate to
+ * @returns {React.Component} OtherProfileFilter
+ */
+function OtherProfileFilter(props) {
+  const { subTitle2 } = props;
+  return (
+    <FilterBox>
+      <OtherProfileFilterSmall subTitle2={subTitle2} />
+      <OtherProfileFilterFull subTitle2={subTitle2} />
+    </FilterBox>
+  );
+}
+
+export default OtherProfileFilter;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileFilter_OtherProfileFilterFull_OtherProfileFilterFull.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileFilter_OtherProfileFilterFull_OtherProfileFilterFull.jsx.html new file mode 100644 index 00000000..bac6b6eb --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileFilter_OtherProfileFilterFull_OtherProfileFilterFull.jsx.html @@ -0,0 +1,167 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilterFull/OtherProfileFilterFull.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilterFull/OtherProfileFilterFull.jsx

+ + + + + + +
+
+
import { useState, useMemo } from 'react';
+import { useLocation, useNavigate, useParams } from 'react-router-dom';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+
+// filled
+import NewReleasesIcon from '@mui/icons-material/NewReleases';
+import LocalFireDepartmentIcon from '@mui/icons-material/LocalFireDepartment';
+import CloudUploadIcon from '@mui/icons-material/CloudUpload';
+
+// outlined
+import NewReleasesOutlinedIcon from '@mui/icons-material/NewReleasesOutlined';
+import LocalFireDepartmentOutlinedIcon from '@mui/icons-material/LocalFireDepartmentOutlined';
+import CloudUploadOutlinedIcon from '@mui/icons-material/CloudUploadOutlined';
+import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
+import {
+  FilteButton, FilterFullBox, SelectBox, SelectItem,
+} from '../styles';
+
+function useQuery() {
+  const { search } = useLocation();
+
+  return useMemo(() => new URLSearchParams(search), [search]);
+}
+
+/**
+ * filter posts by their type for large screens
+ *
+ * @component OtherProfileFilterFull
+ * @property {string} subTitle -subTitle of page the user is currently in
+ * @returns {React.Component} OtherProfileFilterFull
+ */
+function OtherProfileFilterFull(props) {
+  const { subTitle2 } = props;
+  const query = useQuery();
+  const sort = query.get('sort');
+  const navigate = useNavigate();
+  const newCondition = (sort === 'new');
+  const hotCondition = (sort === 'hot');
+  const topCondition = (sort === 'top' || sort === 'top&t=day');
+  const [showList, setShowList] = useState(false);
+  const [allTime, setAllTime] = useState('All Time');
+  const { username } = useParams();
+
+  // navigate
+  const handleClick = (subPage) => {
+    setAllTime('All Time');
+    navigate(`/user/${username}/${subTitle2}?sort=${subPage}`);
+  };
+  const handleClick2 = () => {
+    setAllTime('Today');
+    navigate(`/user/${username}/${subTitle2}?sort=top&t=day`);
+  };
+  const handleClickList = () => {
+    setShowList((prev) => !prev);
+  };
+
+  const handleClickAway = () => {
+    setShowList(false);
+  };
+  return (
+    <FilterFullBox>
+      <FilteButton
+        startIcon={(newCondition || (!hotCondition && !topCondition)) ? <NewReleasesIcon /> : <NewReleasesOutlinedIcon />}
+        condition={(newCondition || (!hotCondition && !topCondition)).toString()}
+        onClick={() => { handleClick('new'); }}
+      >
+        New
+      </FilteButton>
+
+      <FilteButton
+        startIcon={hotCondition ? <LocalFireDepartmentIcon /> : <LocalFireDepartmentOutlinedIcon />}
+        condition={hotCondition.toString()}
+        onClick={() => { handleClick('hot'); }}
+      >
+        Hot
+      </FilteButton>
+
+      <FilteButton
+        startIcon={topCondition ? <CloudUploadIcon /> : <CloudUploadOutlinedIcon />}
+        condition={topCondition.toString()}
+        onClick={() => { handleClick('top'); }}
+      >
+        Top
+      </FilteButton>
+      {
+          topCondition && (
+            <FilteButton
+              endIcon={<KeyboardArrowDownOutlinedIcon />}
+              condition={true.toString()}
+              onClick={() => { handleClickList(); }}
+            >
+              {allTime}
+                {showList && (
+                <ClickAwayListener onClickAway={handleClickAway}>
+                  <SelectBox>
+                    <SelectItem
+                      color="inherit"
+                      onClick={() => { handleClick2(); }}
+                      condition={(sort === 'top&t=day').toString()}
+                    >
+                      Today
+
+                    </SelectItem>
+                  </SelectBox>
+                </ClickAwayListener>
+                )}
+            </FilteButton>
+
+          )
+        }
+
+    </FilterFullBox>
+  );
+}
+
+export default OtherProfileFilterFull;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileFilter_OtherProfileFilterSmall_OtherProfileFilterSmall.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileFilter_OtherProfileFilterSmall_OtherProfileFilterSmall.jsx.html new file mode 100644 index 00000000..35b6eab1 --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileFilter_OtherProfileFilterSmall_OtherProfileFilterSmall.jsx.html @@ -0,0 +1,255 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilterSmall/OtherProfileFilterSmall.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilterSmall/OtherProfileFilterSmall.jsx

+ + + + + + +
+
+
// outlined
+import NewReleasesOutlinedIcon from '@mui/icons-material/NewReleasesOutlined';
+import LocalFireDepartmentOutlinedIcon from '@mui/icons-material/LocalFireDepartmentOutlined';
+import CloudUploadOutlinedIcon from '@mui/icons-material/CloudUploadOutlined';
+import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
+import { useLocation, useNavigate, useParams } from 'react-router-dom';
+import { ClickAwayListener } from '@mui/material';
+import { useState, useMemo } from 'react';
+import {
+  FilteButton, FilterSmallBox, SelectBox, SelectItem,
+} from '../styles';
+
+// choose to render one of the new - hot - top buttons in smaller screens
+const renderSwitch = (
+  newCondition,
+  hotCondition,
+  topCondition,
+  handleClickList,
+  handleClickList2,
+  showList2,
+  handleClick2,
+  handleClickAway2,
+  sort,
+  allTime,
+) => {
+  if (newCondition) {
+    return (
+      <FilteButton
+        startIcon={<NewReleasesOutlinedIcon />}
+        condition="true"
+        onClick={() => { handleClickList(); }}
+        endIcon={<KeyboardArrowDownOutlinedIcon />}
+        data-testid="new-btn"
+      >
+        New
+      </FilteButton>
+    );
+  }
+
+  if (hotCondition) {
+    return (
+      <FilteButton
+        startIcon={<LocalFireDepartmentOutlinedIcon />}
+        condition="true"
+        onClick={() => { handleClickList(); }}
+        endIcon={<KeyboardArrowDownOutlinedIcon />}
+      >
+        HOT
+      </FilteButton>
+    );
+  }
+  if (topCondition) {
+    // top and all time button and its show more menu
+    return (
+      <>
+        <FilteButton
+          startIcon={<CloudUploadOutlinedIcon />}
+          condition="true"
+          onClick={() => { handleClickList(); }}
+          endIcon={<KeyboardArrowDownOutlinedIcon />}
+        >
+          TOP
+        </FilteButton>
+        <FilteButton
+          endIcon={<KeyboardArrowDownOutlinedIcon />}
+          condition="true"
+          onClick={() => { handleClickList2(); }}
+        >
+          {allTime}
+          {showList2 && (
+            <ClickAwayListener onClickAway={handleClickAway2}>
+              <SelectBox>
+                <SelectItem
+                  color="inherit"
+                  onClick={() => { handleClick2(); }}
+                  condition={(sort === 'top&t=day').toString()}
+                >
+                  Today
+
+                </SelectItem>
+              </SelectBox>
+            </ClickAwayListener>
+          )}
+        </FilteButton>
+      </>
+    );
+  }
+  return (
+    <div />
+  );
+};
+
+function useQuery() {
+  const { search } = useLocation();
+
+  return useMemo(() => new URLSearchParams(search), [search]);
+}
+
+/**
+ * Filter the posts by type for small screens
+ *
+ * @component OtherProfileFilterSmall
+ * @property {string} subTitle -subTitle of page the user is currently in
+ * @returns {React.Component} OtherProfileFilterSmall
+ */
+
+function OtherProfileFilterSmall(props) {
+  const { subTitle2 } = props;
+  const query = useQuery();
+  const sort = query.get('sort');
+  const navigate = useNavigate();
+  // check the url of the page i m currently in
+  const hotCondition = (sort === 'hot');
+  const topCondition = (sort === 'top' || sort === 'top&t=day');
+  // new by default
+  const newCondition = !hotCondition && !topCondition;
+  const [showList, setShowList] = useState(false);
+  const [showList2, setShowList2] = useState(false);
+  const [allTime, setAllTime] = useState('All Time');
+  const { username } = useParams();
+
+  const handleClick = (subPage) => {
+    setAllTime('All Time');
+    navigate(`/user/${username}/${subTitle2}?sort=${subPage}`);
+  };
+  const handleClick2 = () => {
+    setAllTime('Today');
+    navigate(`/user/${username}/${subTitle2}?sort=top&t=day`);
+  };
+
+  // show list of new - hot - top
+  const handleClickList = () => {
+    setShowList((prev) => !prev);
+  };
+
+  const handleClickAway = () => {
+    setShowList(false);
+  };
+
+  // show list of all time
+  const handleClickList2 = () => {
+    setShowList2((prev) => !prev);
+  };
+
+  const handleClickAway2 = () => {
+    setShowList2(false);
+  };
+
+  const content = [
+    {
+      id: 1, text: 'New', nav: 'new', icon: <NewReleasesOutlinedIcon />, condition: !hotCondition && !topCondition,
+    },
+    {
+      id: 2, text: 'Hot', nav: 'hot', icon: <LocalFireDepartmentOutlinedIcon />, condition: hotCondition,
+    },
+    {
+      id: 3, text: 'Top', nav: 'top', icon: <CloudUploadOutlinedIcon />, condition: topCondition,
+    },
+  ];
+
+  return (
+    <FilterSmallBox>
+      {renderSwitch(
+        newCondition,
+        hotCondition,
+        topCondition,
+        handleClickList,
+        handleClickList2,
+        showList2,
+        handleClick2,
+        handleClickAway2,
+        sort,
+        allTime,
+      )}
+
+      {showList && (
+        <ClickAwayListener onClickAway={handleClickAway}>
+          <SelectBox sx={{ marginTop: -1, marginLeft: 0 }} data-testid="more-menu">
+            { content.map((entity) => (
+              <FilteButton
+                key={entity.id}
+                startIcon={entity.icon}
+                condition={(entity.condition).toString()}
+                onClick={() => { handleClick(`${entity.nav}`); }}
+                sx={{
+                  borderRadius: 0,
+                  '&:hover': {
+                    color: 'black',
+                    bgcolor: '#e9f5fd',
+                  },
+                }}
+              >
+                {entity.text}
+              </FilteButton>
+            ))}
+          </SelectBox>
+        </ClickAwayListener>
+      )}
+
+    </FilterSmallBox>
+  );
+}
+
+export default OtherProfileFilterSmall;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileMainContent.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileMainContent.jsx.html new file mode 100644 index 00000000..b60e4249 --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileMainContent.jsx.html @@ -0,0 +1,112 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileMainContent.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileMainContent.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import CommunitiesProvider from '../../../../contexts/CommunitiesModeratorContext';
+import CommentsTap from '../../CommentsTap/CommentsTap';
+import CommunitiesSubscriberProvider from '../../../../contexts/CommunitiesSubscriberContext';
+import UserProvider from '../../../../contexts/UserProvider';
+import OtherProfileContent from './OtherProfileContent/OtherProfileContent';
+import OtherProfilePostsTap from './OtherProfilePostsTap/OtherProfilePostsTap';
+import OtherProfileSidebar from './OtherProfileSidebar/OtherProfileSidebar';
+import { ProfilePage } from './styles';
+
+const renderSwitch = (param) => {
+  if (param === undefined || param === '?sort=new' || param === '?sort=hot' || param === '?sort=top' || param === '?sort=top&t=day') {
+    return (
+      <OtherProfileContent />
+    );
+  }
+
+  if (param === 'submitted') {
+    return (
+      <OtherProfilePostsTap />
+    );
+  }
+  if (param === 'comments') {
+    return (
+      <CommentsTap profile={false} />
+    );
+  }
+  return (
+    <div />
+  );
+};
+
+/**
+ * OtherProfileMainContent if the profile page
+ *
+ * @component MainContentProfile
+ * @property  {function} handleClick to navigate to the subpage
+ * @return {React.Component} - OtherProfileMainContent
+ */
+
+function OtherProfileMainContent() {
+  const { subTitle, username } = useParams();
+
+  return (
+    <Box>
+      <UserProvider name={username}>
+        <CommunitiesSubscriberProvider>
+          <CommunitiesProvider>
+            <ProfilePage>
+              {renderSwitch(subTitle)}
+              <OtherProfileSidebar />
+            </ProfilePage>
+          </CommunitiesProvider>
+        </CommunitiesSubscriberProvider>
+      </UserProvider>
+    </Box>
+  );
+}
+
+export default OtherProfileMainContent;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePostsTap_OtherProfilePostsTap.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePostsTap_OtherProfilePostsTap.jsx.html new file mode 100644 index 00000000..38b4369b --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePostsTap_OtherProfilePostsTap.jsx.html @@ -0,0 +1,103 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/OtherProfilePostsTap.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/OtherProfilePostsTap.jsx

+ + + + + + +
+
+
import { useLocation, useParams } from 'react-router-dom';
+import { useEffect, useState, useMemo } from 'react';
+// import InfiniteScroll from 'react-infinite-scroll-component';
+import { postsCommentsServer } from '../../../profileServer';
+import Filter from '../OtherProfileFilter/OtherProfileFilter';
+import { WideBox } from '../styles';
+import EmptyContent from '../OtherProfileEmptyContent/OtherProfileEmptyContent';
+import Post from '../OtherProfilePosts/OtherProfilePost';
+// import { useListingContext } from '../../../../../contexts/ListingContext';
+
+function useQuery() {
+  const { search } = useLocation();
+
+  return useMemo(() => new URLSearchParams(search), [search]);
+}
+
+/**
+ * posts tap in my profile
+ *
+ * @component OtherProfilePostsTap
+ * @returns {React.Component} OtherProfilePostsTap
+ */
+function OtherProfilePostsTap() {
+  const { subTitle, username } = useParams();
+  const query = useQuery();
+  const sort = query.get('sort');
+  const [posts] = postsCommentsServer(username, 'posts', sort || 'new');
+  const [isContent, setIsContent] = useState(false);
+
+  // check if the page have any content posts to show
+  useEffect(() => {
+    console.log(posts);
+    setIsContent(false);
+    if (posts?.length > 0) { setIsContent(true); }
+  }, [username, posts, sort]);
+
+  const emptyContent = `hmm... u/${username}
+          hasn't posted recently`;
+  return (
+    <WideBox>
+      <Filter subTitle2={`${subTitle}/`} />
+      {!isContent && <EmptyContent emptyContent={emptyContent} />}
+      {isContent
+          && (
+            posts.map((entity, index) => (<Post key={`${index + 0}`} entity={entity} />))
+          )}
+
+    </WideBox>
+  );
+}
+
+export default OtherProfilePostsTap;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfileFooter_OtherProfileArrowList_OtherProfileArrowList.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfileFooter_OtherProfileArrowList_OtherProfileArrowList.jsx.html new file mode 100644 index 00000000..9eb55bb2 --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfileFooter_OtherProfileArrowList_OtherProfileArrowList.jsx.html @@ -0,0 +1,109 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfileArrowList/OtherProfileArrowList.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfileArrowList/OtherProfileArrowList.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+import {
+  DownArrow,
+  DownArrowFilled,
+  Number, UpArrow, UpArrowFilled, Votes,
+} from './styles';
+import { postReactionsServer } from '../../../../../profileServer';
+
+/**
+ * the upvoted and downvoted arrows in responsive postfooter
+ *
+ * @component ArrowList
+ * @property {number} points - get number of upvotes or downvotes on a post
+ * @property {number} postVoteStatus - get if the post is upvoted or downvoted or none
+ * @returns {React.Component} ArrowList
+ */
+function OtherProfileArrowList(props) {
+  const { postid, points, postVoteStatus } = props;
+  const [postPoints, setPostPoints] = useState(points);
+  const [status, setStatus] = useState(postVoteStatus);
+
+  const handleClickUp = () => {
+    postReactionsServer(postid, 'vote', 1);
+    if (status === '-1') setPostPoints(postPoints + 2);
+    else setPostPoints(postPoints + 1);
+    setStatus('1');
+  };
+  const handleClickDown = () => {
+    postReactionsServer(postid, 'vote', -1);
+    if (status === '1') setPostPoints(postPoints - 2);
+    else setPostPoints(postPoints - 1);
+    setStatus('-1');
+  };
+  const handleNoUpvote = () => {
+    postReactionsServer(postid, 'vote', 0);
+    setPostPoints(postPoints - 1);
+    setStatus('0');
+  };
+  const handleNoDownvote = () => {
+    postReactionsServer(postid, 'vote', 0);
+    setPostPoints(postPoints + 1);
+    setStatus('0');
+  };
+
+  return (
+    <Votes>
+      {
+        (status === '1') ? <UpArrowFilled onClick={() => { handleNoUpvote(); }} /> : <UpArrow onClick={() => { handleClickUp(); }} />
+      }
+      <Number variant="caption" sx={{ fontWeight: 700 }}>{postPoints}</Number>
+      {
+        (status === '-1') ? <DownArrowFilled onClick={() => { handleNoDownvote(); }} /> : <DownArrow onClick={() => { handleClickDown(); }} />
+      }
+    </Votes>
+  );
+}
+
+export default OtherProfileArrowList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfileFooter_OtherProfilePostFooter.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfileFooter_OtherProfilePostFooter.jsx.html new file mode 100644 index 00000000..6118a563 --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfileFooter_OtherProfilePostFooter.jsx.html @@ -0,0 +1,269 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooter.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooter.jsx

+ + + + + + +
+
+
import ChatBubbleOutlineOutlinedIcon from '@mui/icons-material/ChatBubbleOutlineOutlined';
+import ShortcutOutlinedIcon from '@mui/icons-material/ShortcutOutlined';
+import MoreHorizOutlinedIcon from '@mui/icons-material/MoreHorizOutlined';
+
+import { useEffect, useState } from 'react';
+import { ClickAwayListener, Divider } from '@mui/material';
+import BookmarkBorderOutlinedIcon from '@mui/icons-material/BookmarkBorderOutlined';
+import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
+import UnfoldLessOutlinedIcon from '@mui/icons-material/UnfoldLessOutlined';
+import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined';
+import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined';
+import BlockOutlinedIcon from '@mui/icons-material/BlockOutlined';
+import AdminPanelSettingsOutlinedIcon from '@mui/icons-material/AdminPanelSettingsOutlined';
+import CancelPresentationOutlinedIcon from '@mui/icons-material/CancelPresentationOutlined';
+import FlagOutlinedIcon from '@mui/icons-material/FlagOutlined';
+import BookmarksOutlinedIcon from '@mui/icons-material/BookmarksOutlined';
+import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
+import { useNavigate } from 'react-router-dom';
+import {
+  ElementBox, FooterBox, FooterText,
+} from './styles';
+import OtherProfilePostFooterListResponsive from './OtherProfilePostFooterListResponsive/OtherProfilePostFooterListResponsive';
+import OtherProfileArrowList from './OtherProfileArrowList/OtherProfileArrowList';
+import { postReactionsServer } from '../../../../profileServer';
+import ModeratorList from '../../../../ModeratorList/ModeratorList';
+
+import { useEditPostContext } from '../../../../../../contexts/EditPostContext';
+
+/**
+ * Footer of the post that contain all icons
+ *
+ * @component OtherProfilePostFooter
+ * @property {function} handleExpand - pass the event to the parent to show the paragraph of the post
+ * @property {state} expand - pass a state to the parent to change the icon
+ * @property {object} entity - contains all info of the post
+ * @returns {React.Component} OtherProfilePostFooter
+ */
+function OtherProfilePostFooter(props) {
+  const {
+    postid, numComments, handleExpand, expand, saved, hidden, submitted, ownerType, owner,
+    points, postVoteStatus, isModList, modState, nsfw, spoiler, locked,
+    handleLock, handleSpoiler, handleNsfw, handleApprove, handleRemove, handleSpam,
+  } = props;
+  const [isHidden, setIsHidden] = useState(hidden);
+  const [isSaved, setIsSaved] = useState(saved);
+  const [showList2, setShowList2] = useState(false);
+  const [modList, setModList] = useState(false);
+  const [moderatorList, setModeratorList] = useState(false);
+
+  const navigate = useNavigate();
+  const { setEditPost, setCommentPost } = useEditPostContext();
+
+  // handle disable the list when click away
+  const handleClick2 = () => {
+    setShowList2((prev) => !prev);
+  };
+
+  const handleClickAway2 = () => {
+    setShowList2(false);
+  };
+
+  // switch icon to hidden post and vice verse
+  const handleClickHide = () => {
+    postReactionsServer(postid, hidden ? 'unhide' : 'hide', hidden);
+    setIsHidden((prev) => !prev);
+  };
+
+  const handleModList = () => {
+    setModeratorList((prev) => !prev);
+  };
+
+  const handleModListClickAway = () => {
+    setModeratorList(false);
+  };
+
+  // switch icon to saved post and vice versa
+  const handleClickSave = () => {
+    postReactionsServer(postid, saved ? 'unsave' : 'save', saved);
+    setIsSaved((prev) => !prev);
+  };
+
+  const handleShare = () => {
+    navigate(`/submit/${postid}`);
+  };
+
+  useEffect(() => {
+    setIsSaved(saved);
+    setIsHidden(hidden);
+    setModList(isModList);
+  }, [saved, hidden, modList]);
+
+  const publisher = [
+    isSaved ? {
+      id: 1, text: 'Unsave', icon: <BookmarksOutlinedIcon />, func: handleClickSave,
+    } : {
+      id: 1, text: 'Save', icon: <BookmarkBorderOutlinedIcon />, func: handleClickSave,
+    },
+    isHidden ? {
+      id: 2, text: 'Unhide', icon: <VisibilityOffIcon />, func: handleClickHide,
+    } : {
+      id: 2, text: 'Hide', icon: <VisibilityOffOutlinedIcon />, func: handleClickHide,
+    },
+  ];
+
+  const moderator = [
+    {
+      id: 1, text: 'Approved', condition: modState === 'approved', icon: <CheckCircleOutlineOutlinedIcon />, func: handleApprove,
+    },
+    {
+      id: 2, text: 'Removed', condition: modState === 'removed', icon: <BlockOutlinedIcon />, func: handleRemove,
+    },
+    {
+      id: 3, text: 'Spam', condition: modState === 'spammed', icon: <CancelPresentationOutlinedIcon />, func: handleSpam,
+    },
+  ];
+  return (
+    <FooterBox>
+      <OtherProfileArrowList postid={postid} points={points} postVoteStatus={postVoteStatus} />
+      <ElementBox>
+        {expand ? <UnfoldLessOutlinedIcon sx={{ rotate: '-45deg' }} onClick={() => { handleExpand(); }} />
+          : <UnfoldMoreOutlinedIcon sx={{ rotate: '-45deg' }} onClick={() => { handleExpand(); }} />}
+      </ElementBox>
+      <Divider orientation="vertical" variant="middle" flexItem />
+      {/* number of comments and share section */}
+
+      <ElementBox onClick={() => { setCommentPost(true); setEditPost(false); navigate(`/${ownerType === 'Subreddit' ? 'r' : 'user'}/${owner}/comments/${postid}`); }}>
+        <ChatBubbleOutlineOutlinedIcon />
+        <FooterText variant="caption" responsiveshare={true.toString()}>
+          {numComments}
+          {' '}
+          Comments
+        </FooterText>
+      </ElementBox>
+      <ElementBox onClick={handleShare}>
+        <ShortcutOutlinedIcon />
+        <FooterText variant="caption" responsiveshare={true.toString()}>Share</FooterText>
+      </ElementBox>
+
+      {/* number of comments and share section */}
+
+      {(submitted && modList) && moderator.map((entity) => (
+        <ElementBox
+          key={entity.id}
+          approved={(entity.condition && entity.text === 'Approved')?.toString()}
+          spam={(entity.condition && (entity.text === 'Spam' || entity.text === 'Removed'))?.toString()}
+          modicons={true.toString()}
+          onClick={entity.func}
+        >
+          {entity.icon}
+          <FooterText variant="caption" condition={true.toString()}>{entity.text}</FooterText>
+        </ElementBox>
+      ))}
+
+      {(submitted && modList) && (
+      <>
+        <ClickAwayListener onClickAway={handleModListClickAway}>
+          <ElementBox>
+            <AdminPanelSettingsOutlinedIcon onClick={handleModList} />
+            {moderatorList && (
+            <ModeratorList
+              postid={postid}
+              nsfw={nsfw}
+              spoiler={spoiler}
+              locked={locked}
+              handleNsfw={handleNsfw}
+              handleSpoiler={handleSpoiler}
+              handleLock={handleLock}
+            />
+            )}
+          </ElementBox>
+        </ClickAwayListener>
+        <ClickAwayListener onClickAway={handleClickAway2}>
+          <ElementBox>
+            <MoreHorizOutlinedIcon onClick={handleClick2} />
+            {showList2 && (
+            <OtherProfilePostFooterListResponsive isSaved={isSaved} postid={postid} />
+            )}
+          </ElementBox>
+        </ClickAwayListener>
+
+      </>
+      )}
+
+      {(submitted && !modList) && (
+      <>
+        {publisher.map((entity) => (
+          <ElementBox
+            key={entity.id}
+            onClick={() => { entity.func(); }}
+            data-testid={(entity.id === 2) && 'hidden'}
+            condition={true.toString()}
+          >
+            {entity.icon}
+            <FooterText variant="caption" condition={true.toString()} data-testid={(entity.id === 2) && 'text-hide'}>{entity.text}</FooterText>
+          </ElementBox>
+        )) }
+        <ElementBox condition={true.toString()}>
+          <FlagOutlinedIcon />
+          <FooterText variant="caption" condition={true.toString()}>Report</FooterText>
+        </ElementBox>
+
+      </>
+      )}
+
+      <ClickAwayListener onClickAway={handleClickAway2}>
+        <ElementBox show={true.toString()}>
+          <MoreHorizOutlinedIcon onClick={handleClick2} />
+          {showList2 && (
+          <OtherProfilePostFooterListResponsive isSaved={isSaved} postid={postid} />
+          )}
+        </ElementBox>
+      </ClickAwayListener>
+
+    </FooterBox>
+  );
+}
+
+export default OtherProfilePostFooter;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfileFooter_OtherProfilePostFooterListResponsive_OtherProfilePostFooterListResponsive.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfileFooter_OtherProfilePostFooterListResponsive_OtherProfilePostFooterListResponsive.jsx.html new file mode 100644 index 00000000..fdf37006 --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfileFooter_OtherProfilePostFooterListResponsive_OtherProfilePostFooterListResponsive.jsx.html @@ -0,0 +1,107 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooterListResponsive/OtherProfilePostFooterListResponsive.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooterListResponsive/OtherProfilePostFooterListResponsive.jsx

+ + + + + + +
+
+
import BookmarkBorderOutlinedIcon from '@mui/icons-material/BookmarkBorderOutlined';
+import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
+import FlagOutlinedIcon from '@mui/icons-material/FlagOutlined';
+import BookmarksOutlinedIcon from '@mui/icons-material/BookmarksOutlined';
+
+import { Divider } from '@mui/material';
+import { useState } from 'react';
+import { SelectBox, SelectItem } from './styles';
+import { postReactionsServer } from '../../../../../profileServer';
+
+/**
+ * resposive list of the post footer
+ *
+ * @component OtherProfilePostFooterListResponsive
+ * @returns {React.Component} OtherProfilePostFooterListResponsive
+ */
+function OtherProfilePostFooterListResponsive(props) {
+  const { postid, isSaved } = props;
+  const [saved, setSaved] = useState(isSaved);
+  const handleClick = () => {
+    postReactionsServer(postid, saved ? 'unsave' : 'save', saved);
+    setSaved((prev) => !prev);
+  };
+  const handleClickHide = () => {
+    postReactionsServer(postid, 'hide', 1);
+  };
+  return (
+    <SelectBox>
+      {!saved ? (
+        <SelectItem onClick={() => { handleClick(); }}>
+          <BookmarkBorderOutlinedIcon sx={{ marginRight: 1 }} />
+          Save
+        </SelectItem>
+      )
+        : (
+          <SelectItem condition={true.toString()} onClick={() => { handleClick(); }}>
+            <BookmarksOutlinedIcon sx={{ marginRight: 1 }} />
+            Unsave
+          </SelectItem>
+        )}
+      <Divider />
+      <SelectItem onClick={() => { handleClickHide(); }}>
+        <VisibilityOffOutlinedIcon sx={{ marginRight: 1 }} />
+        Hide
+      </SelectItem>
+      <Divider />
+      <SelectItem>
+        <FlagOutlinedIcon sx={{ marginRight: 1 }} />
+        Report
+      </SelectItem>
+
+    </SelectBox>
+  );
+}
+
+export default OtherProfilePostFooterListResponsive;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfilePost.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfilePost.jsx.html new file mode 100644 index 00000000..229e59ea --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfilePost.jsx.html @@ -0,0 +1,220 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePost.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePost.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import ArticleOutlinedIcon from '@mui/icons-material/ArticleOutlined';
+import { useState, useContext, useEffect } from 'react';
+
+import { useNavigate } from 'react-router-dom';
+import { CommunitiesContext } from '../../../../../contexts/CommunitiesModeratorContext';
+import { useEditPostContext } from '../../../../../contexts/EditPostContext';
+import {
+  EmptyImage,
+  Flair,
+  PostContentBox,
+  PostImage,
+  PostSidebaRes,
+  PostsQueueBox,
+  TagPost,
+  TitlePost,
+} from './styles';
+import OtherProfilePostSide from './OtherProfilePostSide/OtherProfilePostSide';
+import OtherProfilePostHeader from './OtherProfilePostHeader/OtherProfilePostHeader';
+import OtherProfilePostFooter from './OtherProfileFooter/OtherProfilePostFooter';
+import { UserContext } from '../../../../../contexts/UserProvider';
+import { CommunitiesSubscriberContext } from '../../../../../contexts/CommunitiesSubscriberContext';
+import { actionOnPost, moderationAction } from '../../../profileServer';
+
+/**
+ * the post that appear in posts - saved - hidden - upvoted - downvotep taps
+ *
+ * @component OtherProfilePost
+ * @property {object} entity - an entity conatins all post informations
+ * @property {string} type -subTitle of the page
+ * @returns {React.Component} OtherProfilePost
+ */
+function OtherProfilePost(props) {
+  const {
+    entity,
+    type,
+  } = props;
+  const [expand, setExpand] = useState();
+  const [subTitle, setSubTitle] = useState(type);
+  const [notJoined, setNotJoined] = useState(false);
+  const { username } = useContext(UserContext);
+  const { communities } = useContext(CommunitiesContext);
+  const { communitiesSubscriber } = useContext(CommunitiesSubscriberContext);
+  const [modList, setModList] = useState(false);
+  const [isNsfw, setIsNsfw] = useState(entity?.nsfw);
+  const [isSpoiler, setIsSpoiler] = useState(entity?.spoiler);
+  const [isLocked, setIsLocked] = useState(entity?.locked);
+  const [modState, setModState] = useState(entity?.modState);
+
+  const handleExpand = () => {
+    setExpand((prev) => !prev);
+  };
+
+  useEffect(() => {
+    if (communitiesSubscriber?.filter((element) => element.fixedName === entity.owner.name).length === 0) { setNotJoined(true); }
+    if (entity.ownerType === 'Subreddit' && communities?.filter((element) => element.fixedName === entity.owner.name).length > 0) {
+      setModList(true);
+    }
+    setSubTitle(type);
+  }, [type, communitiesSubscriber, entity]);
+
+  const navigate = useNavigate();
+  const { setEditPost } = useEditPostContext();
+
+  const handleNsfw = () => {
+    actionOnPost(entity?.postid, isNsfw ? 'unmark_nsfw' : 'mark_nsfw');
+    setIsNsfw((prev) => !prev);
+  };
+  const handleSpoiler = () => {
+    actionOnPost(entity?.postid, isSpoiler ? 'unspoiler' : 'spoiler');
+    setIsSpoiler((prev) => !prev);
+  };
+  const handleLock = () => {
+    actionOnPost(entity?.postid, isLocked ? 'unlock_comments' : 'lock_comments');
+    setIsLocked((prev) => !prev);
+  };
+  const handleApprove = () => {
+    moderationAction(entity?.postid, 'approve');
+    setModState('approved');
+  };
+  const handleRemove = () => {
+    moderationAction(entity?.postid, 'remove');
+    setModState('removed');
+  };
+  const handleSpam = () => {
+    moderationAction(entity?.postid, 'spam');
+    setModState('spammed');
+  };
+
+  return (
+    <PostsQueueBox>
+      <OtherProfilePostSide postid={entity?._id} points={entity.votes} postVoteStatus={entity.postVoteStatus} spam={entity.modState === 'spam'} />
+
+      <PostSidebaRes>
+        <Box sx={{ display: 'flex' }}>
+          <EmptyImage onClick={() => { setEditPost(false); navigate(`/${entity?.ownerType === 'Subreddit' ? 'subreddit' : 'user'}/${entity?.owner?.name}/comments/${entity?._id}`); }}>
+            {entity.images.length === 0 ? (
+
+              <ArticleOutlinedIcon fontSize="small" color="disabled" />
+            )
+              : (
+                <PostImage src={entity.images[0]} alt="post pic" />
+              )}
+          </EmptyImage>
+
+          <PostContentBox>
+            <Box sx={{ marginLeft: 1 }}>
+              <Box sx={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }} onClick={() => { setEditPost(false); navigate(`/${entity?.ownerType === 'Subreddit' ? 'subreddit' : 'user'}/${entity?.owner?.name}/comments/${entity?._id}`); }}>
+                <TitlePost variant="h6">{entity.title}</TitlePost>
+                {
+                entity?.flairId?.text
+                    && (
+                    <Flair
+                      disableRipple
+                      backgroundcolor={entity?.flairId?.backgroundColor}
+                      flaircolor={entity?.flairId?.textColor}
+                    >
+                      {entity?.flairId?.text}
+                    </Flair>
+                    )
+                  }
+                {entity.spoiler && <TagPost color="#A4A7A8" variant="caption">spoiler</TagPost>}
+                {entity.nsfw && <TagPost color="#FF585B" variant="caption">nsfw</TagPost>}
+              </Box>
+              <OtherProfilePostHeader
+                type={entity.ownerType}
+                subReddit={entity.owner.name}
+                nameUser={username}
+                Time={entity.createdAt}
+                modState={entity.modState}
+                locked={entity.locked}
+                notJoined={notJoined}
+                sharedFrom={entity?.sharedFrom}
+
+              />
+              <OtherProfilePostFooter
+                postid={entity?._id}
+                handleExpand={handleExpand}
+                expand={expand}
+                submitted={subTitle === undefined}
+                saved={entity.isSaved}
+                hidden={entity.isHidden}
+                numComments={entity.commentCount}
+                points={entity.votes}
+                postVoteStatus={entity.postVoteStatus}
+                nsfw={isNsfw}
+                spoiler={isSpoiler}
+                locked={isLocked}
+                isModList={modList}
+                modState={modState}
+                handleLock={handleLock}
+                handleSpoiler={handleSpoiler}
+                handleNsfw={handleNsfw}
+                handleApprove={handleApprove}
+                handleRemove={handleRemove}
+                handleSpam={handleSpam}
+                ownerType={entity.ownerType}
+                owner={entity.owner.name}
+              />
+            </Box>
+          </PostContentBox>
+        </Box>
+        {expand && <Box dangerouslySetInnerHTML={{ __html: entity?.text }} />}
+      </PostSidebaRes>
+    </PostsQueueBox>
+  );
+}
+
+export default OtherProfilePost;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfilePostHeader_OtherProfilePostHeader.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfilePostHeader_OtherProfilePostHeader.jsx.html new file mode 100644 index 00000000..3cb008f5 --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfilePostHeader_OtherProfilePostHeader.jsx.html @@ -0,0 +1,159 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostHeader/OtherProfilePostHeader.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostHeader/OtherProfilePostHeader.jsx

+ + + + + + +
+
+
import { Typography } from '@mui/material';
+import moment from 'moment/moment';
+import { useState } from 'react';
+import LockIcon from '@mui/icons-material/Lock';
+import Inventory2Icon from '@mui/icons-material/Inventory2';
+import DoDisturbAltIcon from '@mui/icons-material/DoDisturbAlt';
+import CheckCircleIcon from '@mui/icons-material/CheckCircle';
+import CallSplitIcon from '@mui/icons-material/CallSplit';
+
+import {
+  HeaderPost, Joined, LinkCross, LinkTo,
+} from './styles';
+
+/**
+ * Header of the post
+ *
+ * @component OtherProfilePostHeader
+ * @property {string} nameUser -name of the currently loggedin user
+ * @property {string} Time -contains the time of the post
+ * @property {string} nameUser -contains the name of subreddit the post piblished in
+ * @returns {React.Component} OtherProfilePostHeader
+ */
+
+function OtherProfilePostHeader(props) {
+  const {
+    nameUser,
+    Time,
+    subReddit,
+    modState,
+    locked,
+    notJoined,
+    type,
+    sharedFrom,
+
+  } = props;
+
+  const [joined, setJoined] = useState(false);
+
+  const handleJoin = () => {
+    setJoined((prev) => !prev);
+  };
+
+  const [hover, setHover] = useState(false);
+
+  const handleMouseIn = () => {
+    setHover(true);
+  };
+  const handleMouseOut = () => {
+    setHover(false);
+  };
+  return (
+    <HeaderPost>
+
+      <LinkTo to={(type === 'Subreddit') ? `/r/${subReddit}` : `/user/${subReddit}`}>
+        <Typography variant="caption" sx={{ fontWeight: 700, '&:hover': { textDecoration: 'underline' } }}>
+          {type === 'Subreddit' ? 'r/' : 'u/'}
+          {subReddit}
+          {' '}
+          .
+        </Typography>
+      </LinkTo>
+      {(notJoined && type === 'Subreddit') && (
+      <Joined
+        variant={(joined ? 'outlined' : 'contained')}
+        onClick={handleJoin}
+        onMouseEnter={handleMouseIn}
+        onMouseLeave={handleMouseOut}
+        data-testid="join button"
+      >
+        {(joined ? (hover ? 'leave' : 'joined') : 'join')}
+      </Joined>
+      )}
+      <Typography variant="caption" sx={{ color: '#787c7e', marginLeft: 1 }}>
+        Posted by
+      </Typography>
+      <LinkTo to={`/user/${nameUser}`}>
+        <Typography variant="caption" sx={{ color: '#787c7e', marginLeft: 1, '&:hover': { textDecoration: 'underline' } }}>
+          u/
+          {nameUser}
+        </Typography>
+      </LinkTo>
+      {sharedFrom && (
+      <>
+        <CallSplitIcon sx={{ color: '#0079D3', marginLeft: '3px', transform: 'rotate(90deg)' }} fontSize="string" />
+        <Typography variant="caption" sx={{ color: '#787c7e', marginLeft: 1 }}>
+          cross posted by
+          {' '}
+          <LinkCross to={`/user/${sharedFrom?.author?.name}`}>
+            {sharedFrom?.author?.name}
+          </LinkCross>
+        </Typography>
+      </>
+      )}
+      <Typography variant="caption" sx={{ color: '#787c7e', marginLeft: 1 }}>
+        {' '}
+        {(moment.utc(Time).local().startOf('seconds')
+          .fromNow())}
+      </Typography>
+
+      {locked && <LockIcon sx={{ color: '#ffd635', marginLeft: '3px' }} fontSize="string" />}
+      {modState === 'spam' && <Inventory2Icon sx={{ color: '#ff585b', marginLeft: '3px' }} fontSize="string" />}
+      {modState === 'approved' && <CheckCircleIcon sx={{ color: '#75d377', marginLeft: '3px' }} fontSize="string" />}
+      {modState === 'removed' && <DoDisturbAltIcon sx={{ color: '#ff585b', marginLeft: '3px' }} fontSize="string" />}
+    </HeaderPost>
+  );
+}
+
+export default OtherProfilePostHeader;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfilePostSide_OtherProfilePostSide.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfilePostSide_OtherProfilePostSide.jsx.html new file mode 100644 index 00000000..b2e20a82 --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfilePosts_OtherProfilePostSide_OtherProfilePostSide.jsx.html @@ -0,0 +1,108 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostSide/OtherProfilePostSide.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostSide/OtherProfilePostSide.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+import {
+  UpArrow, DownArrow, SidebarQueueBox, UpArrowFilled, DownArrowFilled, Number,
+} from './styles';
+import { postReactionsServer } from '../../../../profileServer';
+
+/**
+ * Sidebar of the post conatining arrow up and down
+ *
+ * @component OtherProfilePostSide
+ * @property {number} points -number of votes on a post
+ * @property {number} postVoteStatus -is the post upvoted or down voted or none
+ * @returns {React.Component} OtherProfilePostSide
+ */
+function OtherProfilePostSide(props) {
+  const {
+    postid, points, postVoteStatus, spam,
+  } = props;
+  const [postPoints, setPostPoints] = useState(points);
+  const [status, setStatus] = useState(postVoteStatus);
+
+  const handleClickUp = () => {
+    postReactionsServer(postid, 'vote', 1);
+    if (status === 1) setPostPoints(postPoints + 2);
+    else setPostPoints(postPoints + 1);
+    setStatus(1);
+  };
+  const handleClickDown = () => {
+    postReactionsServer(postid, 'vote', -1);
+    if (status === 1) setPostPoints(postPoints - 2);
+    else setPostPoints(postPoints - 1);
+    setStatus(-1);
+  };
+  const handleNoUpvote = () => {
+    postReactionsServer(postid, 'vote', 0);
+    setPostPoints(postPoints - 1);
+    setStatus(0);
+  };
+  const handleNoDownvote = () => {
+    postReactionsServer(postid, 'vote', 0);
+    setPostPoints(postPoints + 1);
+    setStatus(0);
+  };
+  return (
+    <SidebarQueueBox condition={spam?.toString()}>
+      {
+        (status === 1) ? <UpArrowFilled onClick={() => { handleNoUpvote(); }} /> : <UpArrow onClick={() => { handleClickUp(); }} />
+      }
+      <Number variant="caption" sx={{ fontWeight: 700 }}>{postPoints}</Number>
+      {
+        (status === -1) ? <DownArrowFilled onClick={() => { handleNoDownvote(); }} /> : <DownArrow onClick={() => { handleClickDown(); }} />
+      }
+    </SidebarQueueBox>
+  );
+}
+
+export default OtherProfilePostSide;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileSidebar_OtherProfileCommunities_OtherProfileCommunities.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileSidebar_OtherProfileCommunities_OtherProfileCommunities.jsx.html new file mode 100644 index 00000000..def5742a --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileSidebar_OtherProfileCommunities_OtherProfileCommunities.jsx.html @@ -0,0 +1,79 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/OtherProfileCommunities.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/OtherProfileCommunities.jsx

+ + + + + + +
+
+
import { Typography } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import { InfoBox } from '../styles';
+import { otherProfileCommunitiesServer } from './otherProfileCommunitiesServer';
+import OtherProfileEntityComment from './OtherProfileEntityCommunity/OtherProfileEntityCommunity';
+
+/**
+ * all comunities you afre a moderator of
+ *
+ * @component OtherProfileCommunities
+ * @returns {React.Component} OtherProfileCommunities
+ */
+
+function OtherProfileCommunities() {
+  // will fetch the comminities here
+  const { username } = useParams();
+  const [communities] = otherProfileCommunitiesServer(username);
+  return (
+    <InfoBox>
+      <Typography variant="body2" sx={{ fontWeight: 700 }}>Moderator of these communities</Typography>
+      {communities?.map((community, index) => (
+        <OtherProfileEntityComment key={`${index + 0}`} community={community} username={username} />
+      ))}
+    </InfoBox>
+  );
+}
+
+export default OtherProfileCommunities;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileSidebar_OtherProfileSidebar.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileSidebar_OtherProfileSidebar.jsx.html new file mode 100644 index 00000000..ea9ca796 --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileSidebar_OtherProfileSidebar.jsx.html @@ -0,0 +1,76 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileSidebar.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileSidebar.jsx

+ + + + + + +
+
+
import { useParams } from 'react-router-dom';
+import BackToTop from '../../../../BackToTop/BackToTop';
+import OtherProfileCommunities from './OtherProfileCommunities/OtherProfileCommunities';
+import { SidebarBox } from './styles';
+import OtherProfileUserInfo from './OtherProfileUserInfo/OtherProfileUserInfo';
+
+/**
+ * sidebar in profile containing the userinfo and communities you are a moderator of
+ *
+ * @component OtherProfileSidebar
+ * @returns {React.Component} OtherProfileSidebar
+ */
+function OtherProfileSidebar() {
+  const { username } = useParams();
+  return (
+    <SidebarBox>
+      <OtherProfileUserInfo username={username} />
+      <OtherProfileCommunities />
+      <BackToTop />
+    </SidebarBox>
+
+  );
+}
+
+export default OtherProfileSidebar;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileSidebar_OtherProfileUserInfo_OtherProfileUserInfo.jsx.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileSidebar_OtherProfileUserInfo_OtherProfileUserInfo.jsx.html new file mode 100644 index 00000000..80103323 --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileSidebar_OtherProfileUserInfo_OtherProfileUserInfo.jsx.html @@ -0,0 +1,248 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/OtherProfileUserInfo.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/OtherProfileUserInfo.jsx

+ + + + + + +
+
+
import { Box, CardMedia, Typography } from '@mui/material';
+import FilterVintageIcon from '@mui/icons-material/FilterVintage';
+import CakeIcon from '@mui/icons-material/Cake';
+import { useEffect, useState } from 'react';
+import moment from 'moment/moment';
+
+import UserInfoServer, { followRequest } from '../../../../mainProfileServer';
+import {
+  ProfilePic, ProfileBox,
+  UserInfoBox, UserName, InfoBox,
+  EntityBox, MoreOptions, OptionsButtons, UserInfoButton, LinkTo, Text, PlatformIcon, BlockButton, BootstrapDialog,
+} from './styles';
+import { blockRequest } from './userActionServer';
+import Block from './Block/Block';
+
+/**
+ * UserInfo Box in sidebar containing all info of a user
+ *
+ * @component OtherProfileUserInfo
+ * @returns {React.Component} OtherProfileUserInfo
+ */
+function OtherProfileUserInfo({ username }) {
+  const [displayName, setDisplayName] = useState();
+  const [about, setAbout] = useState();
+  const [postKarma, setPostKarma] = useState();
+  const [commentKarma, setCommentKarma] = useState();
+  const [cake, setCake] = useState();
+  const [profilePic, setProfilePic] = useState();
+  const [coverPic, setCoverPic] = useState();
+  const [follow, setFollow] = useState(undefined);
+  const [isFollowedUi, setIsFollowedUi] = useState(undefined);
+  const [socialLinks, setSocialLinks] = useState([]);
+  const [block, setBlock] = useState(undefined);
+
+  const [hover, setHover] = useState(false);
+
+  const [open, setOpen] = useState(false);
+
+  const [info, statusCode] = UserInfoServer(username);
+  followRequest(username, follow, () => { setIsFollowedUi((prev) => !prev); });
+  blockRequest(username, block);
+
+  useEffect(() => {
+    setDisplayName(info?.displayName);
+    setAbout(info?.description);
+    setPostKarma(info?.postKarma);
+    setCommentKarma(info?.commentKarma);
+    setCake(info?.createdAt);
+    setProfilePic(info?.profilePicture);
+    setCoverPic(info?.profileBackground);
+    setFollow(info?.isFollowed);
+    setIsFollowedUi(info?.isFollowed);
+    setSocialLinks(info?.socialLinks);
+    setBlock(info?.isBlocked);
+  }, [info, statusCode]);
+
+  const [showList, setShowList] = useState(false);
+
+  const handleClickList = () => {
+    setShowList((prev) => !prev);
+  };
+
+  const handleClickFollow = () => {
+    setFollow((prev) => !prev);
+  };
+
+  const handleBlock = () => {
+    setOpen(true);
+  };
+
+  const handleBlockApprove = () => {
+    setOpen(false);
+    setBlock((prev) => !prev);
+  };
+
+  const handleMouseIn = () => {
+    setHover(true);
+  };
+  const handleMouseOut = () => {
+    setHover(false);
+  };
+
+  return (
+    <UserInfoBox>
+      <CardMedia
+        component="img"
+        height="94"
+        image={coverPic}
+        alt="cover image"
+        data-testid="cover-photo"
+      />
+
+      <ProfileBox>
+        <Box sx={{ display: 'flex' }}>
+          <Box>
+            <ProfilePic src={profilePic} alt="user photo" />
+          </Box>
+        </Box>
+        <UserName variant="string">
+          {displayName}
+        </UserName>
+        <br />
+        <UserName variant="caption">
+          u/
+          {username}
+        </UserName>
+        <UserName variant="body2" sx={{ marginTop: '5px' }}>
+          {about}
+        </UserName>
+        <InfoBox>
+          <EntityBox>
+            <Typography variant="body2" sx={{ marginBottom: '5px' }}>Karma</Typography>
+            <Box sx={{ display: 'flex' }}>
+              <FilterVintageIcon fontSize="string" color="primary" sx={{ marginRight: '4px' }} />
+              <Typography variant="caption" sx={{ color: '#7c7c7c' }}>{postKarma + commentKarma }</Typography>
+            </Box>
+          </EntityBox>
+          <EntityBox>
+            <Typography variant="body2" sx={{ marginBottom: '5px' }}>Cake Day</Typography>
+            <Box sx={{ display: 'flex' }}>
+              <CakeIcon fontSize="string" color="primary" sx={{ marginRight: '4px' }} />
+              <Typography variant="caption" sx={{ color: '#7c7c7c' }}>{moment(cake, 'YYYY-MM-DD-HH-mm').add(1, 'days').utc().format('MMMM DD, YYYY')}</Typography>
+            </Box>
+          </EntityBox>
+        </InfoBox>
+
+        {/* social link part */}
+        <Box sx={{ display: 'flex', flexWrap: 'wrap' }}>
+          {socialLinks?.map((link, index) => (
+            <LinkTo href={`${link?.userLink}`} target="_blank">
+              <Text key={`${index + 0}`}>
+                <PlatformIcon src={link?.social?.icon} />
+                {link?.displayText}
+              </Text>
+            </LinkTo>
+          ))}
+        </Box>
+        {/* social link part */}
+
+        {!block ? (
+          <>
+            <Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
+              {isFollowedUi ? <UserInfoButton variant="outlined" onClick={() => { handleClickFollow(); }}>Unfollow</UserInfoButton> : <UserInfoButton variant="contained" onClick={() => { handleClickFollow(); }}>Follow</UserInfoButton>}
+              <UserInfoButton variant="contained">Chat</UserInfoButton>
+            </Box>
+            {showList
+            && (
+            <>
+              <OptionsButtons data-testid="option">Send Message</OptionsButtons>
+              <OptionsButtons onClick={() => { handleBlockApprove(); }}>Block User</OptionsButtons>
+              <OptionsButtons>Get Them Help and Support</OptionsButtons>
+              <OptionsButtons>Report User</OptionsButtons>
+              <OptionsButtons>Add to Custom Feed</OptionsButtons>
+              <MoreOptions onClick={() => { handleClickList(); }}>Fewer options</MoreOptions>
+            </>
+            )}
+            {!showList
+            && <MoreOptions data-testid="show-more" onClick={() => { handleClickList(); }}>More options</MoreOptions>}
+          </>
+        )
+          : (
+            <BlockButton
+              variant="contained"
+              onClick={handleBlock}
+              onMouseEnter={handleMouseIn}
+              onMouseLeave={handleMouseOut}
+            >
+              {(block ? (hover ? 'Unblock' : 'Blocked') : 'Blocked')}
+            </BlockButton>
+          )}
+        <BootstrapDialog
+          onClose={(event, reason) => {
+            if (reason !== 'backdropClick' && reason !== 'escapeKeyDown') {
+              setOpen(false);
+            }
+          }}
+          aria-labelledby="customized-dialog-title"
+          open={open}
+          keepMounted
+        >
+          <Block
+            onClose={(event, reason) => {
+              if (reason !== 'backdropClick' && reason !== 'escapeKeyDown') {
+                setOpen(false);
+              }
+            }}
+            username={username}
+            handleBlock={handleBlockApprove}
+          />
+        </BootstrapDialog>
+      </ProfileBox>
+
+    </UserInfoBox>
+  );
+}
+
+export default OtherProfileUserInfo;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileSidebar_OtherProfileUserInfo_userActionServer.js.html b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileSidebar_OtherProfileUserInfo_userActionServer.js.html new file mode 100644 index 00000000..0f4f8989 --- /dev/null +++ b/docs/components_MainProfile_OtherProfile_OtherProfileMainContent_OtherProfileSidebar_OtherProfileUserInfo_userActionServer.js.html @@ -0,0 +1,88 @@ + + + + + JSDoc: Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/userActionServer.js + + + + + + + + + + +
+ +

Source: components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/userActionServer.js

+ + + + + + +
+
+
import { useRef, useState, useEffect } from 'react';
+
+import axios from '../../../../../../services/instance';
+
+/**
+ * block a user
+ *
+ * @property {string} username - username of blocked user
+ * @returns {object} provided response through backend
+ */
+
+export const blockRequest = (username, block) => {
+  const [data, setData] = useState(null);
+
+  const isFirstRun = useRef(true);
+  useEffect(() => {
+    if (block === undefined) {
+      return;
+    }
+    if (isFirstRun.current) {
+      isFirstRun.current = false;
+      return;
+    }
+    axios.post(`users/${username}/${block ? 'block_user' : 'unblock_user'}`, {
+
+    }).then((response) => {
+      // console.log(response);
+      if (response.status === 401) {
+        window.location.pathname = 'login';
+      }
+      setData(response.data);
+    }).catch((error) => {
+      console.log(error);
+    });
+  }, [username, block]);
+  return [data];
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Posts_PostFooter_PostFooter.jsx.html b/docs/components_MainProfile_Posts_PostFooter_PostFooter.jsx.html new file mode 100644 index 00000000..2abe1ce8 --- /dev/null +++ b/docs/components_MainProfile_Posts_PostFooter_PostFooter.jsx.html @@ -0,0 +1,305 @@ + + + + + JSDoc: Source: components/MainProfile/Posts/PostFooter/PostFooter.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Posts/PostFooter/PostFooter.jsx

+ + + + + + +
+
+
import ChatBubbleOutlineOutlinedIcon from '@mui/icons-material/ChatBubbleOutlineOutlined';
+import ShortcutOutlinedIcon from '@mui/icons-material/ShortcutOutlined';
+import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined';
+import BlockOutlinedIcon from '@mui/icons-material/BlockOutlined';
+import AdminPanelSettingsOutlinedIcon from '@mui/icons-material/AdminPanelSettingsOutlined';
+import MoreHorizOutlinedIcon from '@mui/icons-material/MoreHorizOutlined';
+import CancelPresentationOutlinedIcon from '@mui/icons-material/CancelPresentationOutlined';
+import SignalCellularAltOutlinedIcon from '@mui/icons-material/SignalCellularAltOutlined';
+import CheckBoxIcon from '@mui/icons-material/CheckBox';
+import ModeEditOutlinedIcon from '@mui/icons-material/ModeEditOutlined';
+import FlagOutlinedIcon from '@mui/icons-material/FlagOutlined';
+import { useState } from 'react';
+import { ClickAwayListener, Divider } from '@mui/material';
+import BookmarksOutlinedIcon from '@mui/icons-material/BookmarksOutlined';
+import BookmarkBorderOutlinedIcon from '@mui/icons-material/BookmarkBorderOutlined';
+// import PushPinOutlinedIcon from '@mui/icons-material/PushPinOutlined';
+import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
+import DeleteOutlineOutlinedIcon from '@mui/icons-material/DeleteOutlineOutlined';
+import CropSquareOutlinedIcon from '@mui/icons-material/CropSquareOutlined';
+import { useNavigate } from 'react-router-dom';
+import { useEditPostContext } from '../../../../contexts/EditPostContext';
+import {
+  ElementBox, FooterBox, FooterText, SelectBox, SelectItem,
+} from './styles';
+import {
+  deletePostComment, postReactionsServer,
+} from '../../profileServer';
+import ModeratorList from '../../ModeratorList/ModeratorList';
+
+/**
+ * footer for a post conatining all icons
+ *
+ * @component PostFooter
+ * @property {string} subTitle - to check if a post is a spam or approved
+ * @property {string} numberOfComments - get number of comments in the post
+ * @returns {React.Component} PostFooter
+ */
+function PostFooter(props) {
+  const {
+    postid, numComments, isSaved, subTitle,
+    nsfw, spoiler, locked, owner,
+    modState, sendReplies, handleLock,
+    handleSpoiler, handleNsfw, handleApprove, handleRemove, handleSpam,
+    mod, profile,
+  } = props;
+
+  const [showList, setShowList] = useState(false);
+  const [saved, setSaved] = useState(isSaved);
+  const [moderatorList, setModeratorList] = useState(false);
+  const [isSendReplies, setIsSendReplies] = useState(sendReplies);
+
+  // handle disable the list when click away
+  const handleClick = () => {
+    setShowList((prev) => !prev);
+  };
+
+  const handleClickAway = () => {
+    setShowList(false);
+  };
+
+  // switch icon to hidden post and vice verse
+  const handleClickHide = () => {
+    postReactionsServer(postid, 'hide', 1);
+  };
+
+  const handleSendReplies = () => {
+    setIsSendReplies((prev) => !prev);
+  };
+  const handleDelete = () => {
+    deletePostComment('posts', postid);
+  };
+
+  // switch icon to saved post and vice versa
+  const handleSave = () => {
+    postReactionsServer(postid, saved ? 'unsave' : 'save', saved);
+    setSaved((prev) => !prev);
+  };
+
+  const handleModListClickAway = () => {
+    setModeratorList(false);
+  };
+
+  const handleModList = () => {
+    setModeratorList((prev) => !prev);
+  };
+
+  const navigate = useNavigate();
+  const handleShare = () => {
+    navigate(`/submit/${postid}`);
+  };
+
+  const { setEditPost, setCommentPost } = useEditPostContext();
+
+  return (
+    <FooterBox>
+      <ElementBox onClick={() => { setCommentPost(true); setEditPost(false); navigate(`/${subTitle === 'Subreddit' ? 'r' : 'user'}/${owner}/comments/${postid}`); }}>
+        <ChatBubbleOutlineOutlinedIcon />
+        <FooterText variant="caption" responsiveshare={true.toString()}>
+          {numComments}
+          {profile ? '' : 'Comments'}
+        </FooterText>
+      </ElementBox>
+
+      <ElementBox onClick={handleShare}>
+        <ShortcutOutlinedIcon />
+        <FooterText variant="caption" responsiveshare={true.toString()}>Share</FooterText>
+      </ElementBox>
+
+      {mod
+      && (
+      <>
+        <ElementBox condition2={(modState === 'approved') && 'true'} responsive3icons={true.toString()} onClick={handleApprove}>
+          <CheckCircleOutlineOutlinedIcon />
+          <FooterText variant="caption" responsiveapprove={true.toString()}>{(modState === 'approved') ? 'Approved' : 'Approve'}</FooterText>
+        </ElementBox>
+        <ElementBox condition={(modState === 'removed') && 'true'} responsive3icons={true.toString()} onClick={handleRemove}>
+          <BlockOutlinedIcon />
+          <FooterText variant="caption" responsiveapprove={true.toString()}>{(modState === 'removed') ? 'Removed' : 'Remove'}</FooterText>
+        </ElementBox>
+        <ElementBox condition={(modState === 'spammed') && 'true'} responsive3icons={true.toString()} onClick={handleSpam}>
+          <CancelPresentationOutlinedIcon />
+          <FooterText variant="caption" responsive={true.toString()}>{(modState === 'spam') ? 'Spammed' : 'Spam'}</FooterText>
+        </ElementBox>
+
+        <ClickAwayListener onClickAway={handleModListClickAway}>
+          <ElementBox>
+            <AdminPanelSettingsOutlinedIcon onClick={handleModList} />
+            {moderatorList && (
+            <ModeratorList
+              postid={postid}
+              nsfw={nsfw}
+              spoiler={spoiler}
+              locked={locked}
+              handleLock={handleLock}
+              handleSpoiler={handleSpoiler}
+              handleNsfw={handleNsfw}
+              handleApprove={handleApprove}
+              handleRemove={handleRemove}
+              handleSpam={handleSpam}
+            />
+            )}
+          </ElementBox>
+        </ClickAwayListener>
+      </>
+      )}
+      {profile && (
+      <ElementBox responsive={true.toString()}>
+        <SignalCellularAltOutlinedIcon sx={{ color: '#b279ff' }} />
+        <FooterText variant="caption">Insights</FooterText>
+      </ElementBox>
+      )}
+
+      {(!mod) && (
+      <ElementBox onClick={() => { handleSave(); }} saveresponsive={true.toString()}>
+        {!saved ? <BookmarkBorderOutlinedIcon /> : <BookmarksOutlinedIcon />}
+        <FooterText variant="caption" responsiveshare={true.toString()}>{!saved ? 'Save' : 'Unsave'}</FooterText>
+      </ElementBox>
+      )}
+
+      <ClickAwayListener onClickAway={handleClickAway}>
+        <ElementBox>
+          <MoreHorizOutlinedIcon onClick={handleClick} data-testid="show-more" />
+          {(showList && profile) && (
+          <SelectBox data-testid="more-menu" profile="false">
+            {!mod && (
+            <SelectItem onClick={() => { setEditPost(true); navigate(`/${subTitle === 'Subreddit' ? 'r' : 'user'}/${owner}/comments/${postid}`); }}>
+              <ModeEditOutlinedIcon sx={{ marginRight: 1 }} />
+              Edit Post
+            </SelectItem>
+            )}
+            {mod && (
+              <SelectItem condition={!saved && 'true'} onClick={() => { handleSave(); }}>
+                {!saved
+                  ? (
+                    <>
+                      <BookmarkBorderOutlinedIcon sx={{ marginRight: 1 }} />
+                      Save
+                    </>
+                  ) : (
+                    <>
+                      <BookmarksOutlinedIcon sx={{ marginRight: 1 }} />
+                      Unsave
+                    </>
+                  )}
+              </SelectItem>
+            )}
+            <Divider />
+            <SelectItem onClick={() => { handleClickHide(); }}>
+              <VisibilityOffOutlinedIcon sx={{ marginRight: 1 }} />
+              Hide
+            </SelectItem>
+            <Divider />
+            <SelectItem onClick={() => { handleDelete(); }}>
+              <DeleteOutlineOutlinedIcon sx={{ marginRight: 1 }} />
+              Delete
+            </SelectItem>
+            <Divider />
+            <SelectItem onClick={() => { handleSpoiler(); }}>
+              {!spoiler ? <CropSquareOutlinedIcon sx={{ marginRight: 1 }} /> : <CheckBoxIcon sx={{ marginRight: 1 }} />}
+              Mark As Spoiler
+            </SelectItem>
+            <Divider />
+            <SelectItem onClick={() => { handleNsfw(); }}>
+              {!nsfw ? <CropSquareOutlinedIcon sx={{ marginRight: 1 }} /> : <CheckBoxIcon sx={{ marginRight: 1 }} />}
+              Mark As NSFW
+            </SelectItem>
+
+            <Divider />
+            <SelectItem onClick={() => { handleSendReplies(); }}>
+              {!isSendReplies ? <CropSquareOutlinedIcon sx={{ marginRight: 1 }} /> : <CheckBoxIcon sx={{ marginRight: 1 }} />}
+              Send Me Reply Notifications
+            </SelectItem>
+
+          </SelectBox>
+          )}
+          {(showList && !profile) && (
+          <SelectBox data-testid="more-menu" profile="true">
+            {mod && (
+              <SelectItem condition={!saved && 'true'} onClick={() => { handleSave(); }}>
+                {!saved
+                  ? (
+                    <>
+                      <BookmarkBorderOutlinedIcon sx={{ marginRight: 1 }} />
+                      Save
+                    </>
+                  ) : (
+                    <>
+                      <BookmarksOutlinedIcon sx={{ marginRight: 1 }} />
+                      Unsave
+                    </>
+                  )}
+              </SelectItem>
+            )}
+            <Divider />
+            <SelectItem onClick={() => { handleClickHide(); }}>
+              <VisibilityOffOutlinedIcon sx={{ marginRight: 1 }} />
+              Hide
+            </SelectItem>
+            <Divider />
+            <Divider />
+            <SelectItem>
+              <FlagOutlinedIcon sx={{ marginRight: 1 }} />
+              Report
+            </SelectItem>
+
+          </SelectBox>
+          )}
+        </ElementBox>
+      </ClickAwayListener>
+    </FooterBox>
+  );
+}
+
+export default PostFooter;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Posts_PostHeader_PostHeader.jsx.html b/docs/components_MainProfile_Posts_PostHeader_PostHeader.jsx.html new file mode 100644 index 00000000..e22fa517 --- /dev/null +++ b/docs/components_MainProfile_Posts_PostHeader_PostHeader.jsx.html @@ -0,0 +1,178 @@ + + + + + JSDoc: Source: components/MainProfile/Posts/PostHeader/PostHeader.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Posts/PostHeader/PostHeader.jsx

+ + + + + + +
+
+
import { Box, Typography } from '@mui/material';
+import moment from 'moment/moment';
+import LockIcon from '@mui/icons-material/Lock';
+import Inventory2Icon from '@mui/icons-material/Inventory2';
+import DoDisturbAltIcon from '@mui/icons-material/DoDisturbAlt';
+import CheckCircleIcon from '@mui/icons-material/CheckCircle';
+import CallSplitIcon from '@mui/icons-material/CallSplit';
+
+import { useState, useEffect } from 'react';
+import PostJoin from '../../../SubReddit/PostJoin';
+import {
+  HeaderAvatar, HeaderAvatarImage, HeaderPost, LinkTo, Joined, LinkCross,
+} from './styles';
+
+/**
+ * Header for a post
+ *
+ * @component PostHeader
+ * @property {string} subReddit - name of subReddit the post published in
+ * @property {string} nameuser - name of publisher
+ * @property {string} time - time of publishing the post
+ * @returns {React.Component} PostHeader
+ */
+
+function PostHeader(props) {
+  const {
+    subReddit, nameUser, Time, type, icon, locked, modState, notJoined, sharedFrom,
+  } = props;
+
+  const [joined, setJoined] = useState(false);
+  const [joinedUI, setJoinedUI] = useState(false);
+
+  const handleJoin = () => {
+    PostJoin(`/subreddits/${subReddit}/subscribe`, joined ? 'unsub' : 'sub');
+    setJoined((prev) => !prev);
+  };
+
+  const [hover, setHover] = useState(false);
+
+  const handleMouseIn = () => {
+    setHover(true);
+  };
+  const handleMouseOut = () => {
+    setHover(false);
+  };
+
+  useEffect(() => {
+    setJoinedUI(!notJoined);
+    setJoined(!notJoined);
+  }, [notJoined]);
+
+  return (
+    <HeaderPost>
+      <Box sx={{
+        display: 'flex',
+        flexWrap: 'wrap',
+      }}
+      >
+        <HeaderAvatar>
+          <HeaderAvatarImage src={icon} />
+        </HeaderAvatar>
+
+        <LinkTo to={(type === 'Subreddit') ? `/r/${subReddit}` : `/user/${subReddit}`}>
+          <Typography variant="caption" sx={{ fontWeight: 700, '&:hover': { textDecoration: 'underline' } }}>
+            {type === 'Subreddit' ? 'r/' : 'u/'}
+            {subReddit}
+            {' '}
+            .
+            {' '}
+          </Typography>
+        </LinkTo>
+        <Typography variant="caption" sx={{ color: '#787c7e', marginLeft: 1 }}>
+          {' '}
+          Posted by
+        </Typography>
+        <LinkTo to={`/user/${nameUser}`}>
+          <Typography variant="caption" sx={{ color: '#787c7e', '&:hover': { textDecoration: 'underline' } }}>
+            u/
+            {nameUser}
+          </Typography>
+        </LinkTo>
+        {sharedFrom && (
+        <>
+          <CallSplitIcon sx={{ color: '#0079D3', marginLeft: '3px', transform: 'rotate(90deg)' }} fontSize="string" />
+          <Typography variant="caption" sx={{ color: '#787c7e', marginLeft: 1 }}>
+            cross posted by
+            {' '}
+            <LinkCross to={`/user/${sharedFrom?.author?.name}`}>
+              {sharedFrom?.author?.name}
+            </LinkCross>
+          </Typography>
+        </>
+        )}
+        <Box sx={{ flex: '1 1 auto', display: 'flex' }}>
+          <Typography
+            variant="caption"
+            sx={{
+              color: '#787c7e', marginLeft: 1,
+            }}
+          >
+            {' '}
+            {(moment.utc(Time).local().startOf('seconds')
+              .fromNow())}
+          </Typography>
+
+          {locked && <LockIcon sx={{ color: '#ffd635', marginLeft: '3px' }} fontSize="string" />}
+          {modState === 'spammed' && <Inventory2Icon sx={{ color: '#ff585b', marginLeft: '3px' }} fontSize="string" />}
+          {modState === 'approved' && <CheckCircleIcon sx={{ color: '#75d377', marginLeft: '3px' }} fontSize="string" />}
+          {modState === 'removed' && <DoDisturbAltIcon sx={{ color: '#ff585b', marginLeft: '3px' }} fontSize="string" />}
+        </Box>
+        {(type === 'Subreddit' && !joinedUI) && (
+        <Joined
+          variant={(joined ? 'outlined' : 'contained')}
+          onClick={handleJoin}
+          onMouseEnter={handleMouseIn}
+          onMouseLeave={handleMouseOut}
+          data-testid="join button"
+        >
+          {(joined ? (hover ? 'leave' : 'joined') : 'join')}
+        </Joined>
+        )}
+      </Box>
+    </HeaderPost>
+  );
+}
+
+export default PostHeader;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Posts_PostSide_PostSide.jsx.html b/docs/components_MainProfile_Posts_PostSide_PostSide.jsx.html new file mode 100644 index 00000000..f1598ed7 --- /dev/null +++ b/docs/components_MainProfile_Posts_PostSide_PostSide.jsx.html @@ -0,0 +1,110 @@ + + + + + JSDoc: Source: components/MainProfile/Posts/PostSide/PostSide.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Posts/PostSide/PostSide.jsx

+ + + + + + +
+
+
import { Typography } from '@mui/material';
+import { useState } from 'react';
+import { postReactionsServer } from '../../profileServer';
+
+import {
+  UpArrow, DownArrow, SidebarQueueBox, UpArrowFilled, DownArrowFilled,
+} from './styles';
+/**
+ * sidebar of the post containing arrow up and down
+ *
+ * @component PostSidebar
+ * @property {number} points -number of points.
+ * @property {number} postVoteStatus -is the post is upvoted or sownvoted.
+ * @returns {React.Component} PostSidebar
+ */
+function PostSide(props) {
+  const {
+    postid, points, postVoteStatus,
+  } = props;
+  const [postPoints, setPostPoints] = useState(points);
+  const [status, setStatus] = useState(postVoteStatus);
+
+  const handleClickUp = () => {
+    postReactionsServer(postid, 'vote', 1);
+    if (status === -1) setPostPoints(postPoints + 2);
+    else setPostPoints(postPoints + 1);
+    setStatus(1);
+  };
+  const handleClickDown = () => {
+    postReactionsServer(postid, 'vote', -1);
+    if (status === 1) setPostPoints(postPoints - 2);
+    else setPostPoints(postPoints - 1);
+    setStatus(-1);
+  };
+  const handleNoUpvote = () => {
+    postReactionsServer(postid, 'vote', 0);
+    setPostPoints(postPoints - 1);
+    setStatus(0);
+  };
+  const handleNoDownvote = () => {
+    postReactionsServer(postid, 'vote', 0);
+    setPostPoints(postPoints + 1);
+    setStatus(0);
+  };
+
+  return (
+    <SidebarQueueBox>
+      {
+        (status === 1) ? <UpArrowFilled onClick={() => { handleNoUpvote(); }} /> : <UpArrow onClick={() => { handleClickUp(); }} />
+      }
+      <Typography variant="caption" sx={{ fontWeight: 700 }}>{postPoints}</Typography>
+      {
+        (status === -1) ? <DownArrowFilled onClick={() => { handleNoDownvote(); }} /> : <DownArrow onClick={() => { handleClickDown(); }} />
+      }
+    </SidebarQueueBox>
+  );
+}
+
+export default PostSide;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Posts_Posts.jsx.html b/docs/components_MainProfile_Posts_Posts.jsx.html new file mode 100644 index 00000000..50c2c64d --- /dev/null +++ b/docs/components_MainProfile_Posts_Posts.jsx.html @@ -0,0 +1,216 @@ + + + + + JSDoc: Source: components/MainProfile/Posts/Posts.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Posts/Posts.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import {
+  useState, useEffect, useContext,
+} from 'react';
+
+import { useNavigate } from 'react-router-dom';
+import { useEditPostContext } from '../../../contexts/EditPostContext';
+import Comments from '../Comments/Comments';
+import PostFooter from './PostFooter/PostFooter';
+import PostHeader from './PostHeader/PostHeader';
+import PostSide from './PostSide/PostSide';
+import {
+  actionOnPost, moderationAction,
+} from '../profileServer';
+import {
+  Flair,
+  PostContentBox,
+  PostsQueueBox,
+  TagPost,
+  TitlePost,
+} from './styles';
+import { CommunitiesContext } from '../../../contexts/CommunitiesModeratorContext';
+import { CommunitiesSubscriberContext } from '../../../contexts/CommunitiesSubscriberContext';
+import PostBody from './PostBody/PostBody';
+import CrossPost from './CrossPost.jsx/CrossPost';
+
+/**
+ * Posts component represents an entity component
+ *
+ * @component Posts
+ * @property {object} post -post entity
+ * @returns {React.Component} Posts
+ */
+function Posts(props) {
+  const {
+    post, condition, profile, nohover,
+  } = props;
+
+  const [isNsfw, setIsNsfw] = useState(post?.nsfw);
+  const [isSpoiler, setIsSpoiler] = useState(post?.spoiler);
+  const [isLocked, setIsLocked] = useState(post?.locked);
+  const [modState, setModState] = useState(post?.modState);
+
+  const { communities } = useContext(CommunitiesContext);
+  const { communitiesSubscriber } = useContext(CommunitiesSubscriberContext);
+
+  const [mod, setMod] = useState(false);
+
+  const [notJoined, setNotJoined] = useState(false);
+
+  useEffect(() => {
+    console.log(post?.kind);
+    if (communitiesSubscriber?.filter((element) => element.fixedName === post?.owner.name).length === 0) {
+      setNotJoined(true);
+    }
+  }, [post, communitiesSubscriber]);
+
+  useEffect(() => {
+    console.log(post?.sharedFrom);
+    if (post.ownerType === 'Subreddit' && communities?.filter((element) => element.fixedName === post.owner.name).length > 0) {
+      setMod(true);
+    }
+  }, [communities, post]);
+
+  const handleNsfw = () => {
+    actionOnPost(post?.postid, isNsfw ? 'unmark_nsfw' : 'mark_nsfw');
+    setIsNsfw((prev) => !prev);
+  };
+  const handleSpoiler = () => {
+    actionOnPost(post?.postid, isSpoiler ? 'unspoiler' : 'spoiler');
+    setIsSpoiler((prev) => !prev);
+  };
+  const handleLock = () => {
+    actionOnPost(post?.postid, isLocked ? 'unlock_comments' : 'lock_comments');
+    setIsLocked((prev) => !prev);
+  };
+  const handleApprove = () => {
+    moderationAction(post?.postid, 'approve');
+    setModState('approved');
+  };
+  const handleRemove = () => {
+    moderationAction(post?.postid, 'remove');
+    setModState('removed');
+  };
+  const handleSpam = () => {
+    moderationAction(post?.postid, 'spam');
+    setModState('spammed');
+  };
+
+  const navigate = useNavigate();
+  const { setEditPost } = useEditPostContext();
+
+  return (
+    <>
+      <PostsQueueBox condition={condition} nohover={nohover}>
+        <PostSide postid={post?._id} points={post?.votes} postVoteStatus={post?.postVoteStatus} />
+        <PostContentBox>
+          <Box sx={{ marginLeft: 1 }}>
+            <PostHeader
+              type={post?.ownerType}
+              subReddit={post?.owner?.name}
+              icon={post?.owner?.icon}
+              nameUser={post?.author?.name}
+              Time={post?.createdAt}
+              locked={isLocked}
+              modState={modState}
+              notJoined={notJoined}
+              sharedFrom={post?.sharedFrom}
+
+            />
+            <Box sx={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }} onClick={() => { setEditPost(false); navigate(`/${post?.ownerType === 'Subreddit' ? 'subreddit' : 'user'}/${post?.owner?.name}/comments/${post?._id}`); }}>
+              <TitlePost variant="h6">{post?.title}</TitlePost>
+              {isSpoiler && <TagPost color="#A4A7A8" variant="caption">spoiler</TagPost>}
+              {isNsfw && <TagPost color="#FF585B" variant="caption">nsfw</TagPost>}
+              {post?.flairId?.text
+                && (
+                <Flair
+                  disableripple
+                  backgroundcolor={post?.flairId?.backgroundColor}
+                  flaircolor={post?.flairId?.textColor}
+                >
+                  {post?.flairId?.text}
+                </Flair>
+                )}
+
+            </Box>
+
+            {!isNsfw && !post?.sharedFrom ? (
+              <PostBody post={post} isSpoiler={isSpoiler} />
+            ) : !isNsfw && post?.sharedFrom && (
+            <CrossPost
+              post={post?.sharedFrom}
+            />
+            )}
+
+            <PostFooter
+              postid={post?._id}
+              isSaved={post?.isSaved}
+              subTitle={post?.ownerType}
+              owner={post?.owner?.name}
+              numComments={post?.commentCount}
+              sendReplies={post?.sendReplies}
+              mod={mod}
+              profile={profile}
+              nsfw={isNsfw}
+              spoiler={isSpoiler}
+              locked={isLocked}
+              modState={modState}
+              handleLock={handleLock}
+              handleSpoiler={handleSpoiler}
+              handleNsfw={handleNsfw}
+              handleApprove={handleApprove}
+              handleRemove={handleRemove}
+              handleSpam={handleSpam}
+            />
+          </Box>
+        </PostContentBox>
+      </PostsQueueBox>
+      {post?.comments
+        && <Comments entity={post} noheader={condition} profile={profile} overview="true" />}
+    </>
+  );
+}
+
+export default Posts;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_Header_ProfileHeader.jsx.html b/docs/components_MainProfile_Profile_Header_ProfileHeader.jsx.html new file mode 100644 index 00000000..8715bb50 --- /dev/null +++ b/docs/components_MainProfile_Profile_Header_ProfileHeader.jsx.html @@ -0,0 +1,170 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/Header/ProfileHeader.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/Header/ProfileHeader.jsx

+ + + + + + +
+
+
import { ClickAwayListener } from '@mui/material';
+import Box from '@mui/material/Box';
+import { useState } from 'react';
+import { useNavigate, useParams } from 'react-router-dom';
+import MoreHorizOutlinedIcon from '@mui/icons-material/MoreHorizOutlined';
+import {
+  PageHeader, HeaderBox, HeaderButton, SelectBox, SelectItem,
+} from './styles';
+
+/**
+ * ProfileHeader
+ * @component
+ * @property  {function} handleClick to navigate to the subpage
+ * @return {React.Component} - Header
+ */
+
+function ProfileHeader() {
+  const { subTitle, username } = useParams();
+  const navigate = useNavigate();
+
+  /**
+   * this function to navigate between the taps
+   * @param {string} subPage - the page to navigate to
+   */
+
+  const handleClick = (subPage) => {
+    navigate(`/user/${username}/${subPage}`);
+  };
+
+  const [showList, setShowList] = useState(false);
+
+  const handleShowList = () => {
+    setShowList((prev) => !prev);
+  };
+
+  const handleClickAway = () => {
+    setShowList(false);
+  };
+
+  const content = [
+    {
+      id: 1, Title: 'Comments', text: 'comments', res: 'res6',
+    },
+    {
+      id: 2, Title: 'History', text: 'history', res: 'res5',
+    },
+    {
+      id: 3, Title: 'Saved', text: 'saved', res: 'res4',
+    },
+    {
+      id: 4, Title: 'Hidden', text: 'hidden', res: 'res3',
+    },
+    {
+      id: 5, Title: 'Upvoted', text: 'upvoted', res: 'res2',
+    },
+    {
+      id: 6, Title: 'Downvoted', text: 'downvoted', res: 'res1',
+    },
+  ];
+
+  return (
+    <Box sx={{ flexGrow: 1 }}>
+      <PageHeader position="static">
+        <HeaderBox subtitle={subTitle}>
+          <HeaderButton
+            color="inherit"
+            onClick={() => { handleClick(''); }}
+            condition={(subTitle === undefined || subTitle.includes('sort')).toString()}
+          >
+            overview
+
+          </HeaderButton>
+          <HeaderButton
+            color="inherit"
+            onClick={() => { handleClick('submitted'); }}
+            condition={(subTitle === 'submitted').toString()}
+            data-testid="posts-tap"
+          >
+            posts
+          </HeaderButton>
+          {content.map((entity) => (
+            <HeaderButton
+              color="inherit"
+              key={entity.id}
+              onClick={() => { handleClick(`${entity.text}`); }}
+              condition={(subTitle === entity.text).toString()}
+              responsive={entity.res}
+            >
+              {entity.Title}
+            </HeaderButton>
+          ))}
+          <ClickAwayListener onClickAway={handleClickAway}>
+            <HeaderButton removedots="true">
+              <MoreHorizOutlinedIcon onClick={handleShowList} color="action" />
+              {showList && (
+
+              <SelectBox>
+                {content.map((entity) => (
+                  <SelectItem
+                    onClick={() => { handleClick(`${entity.text}`); }}
+                    responsive={entity.res}
+                    key={entity.id}
+                  >
+                    {entity.Title}
+                  </SelectItem>
+                ))}
+              </SelectBox>
+
+              )}
+            </HeaderButton>
+          </ClickAwayListener>
+
+        </HeaderBox>
+      </PageHeader>
+    </Box>
+  );
+}
+
+export default ProfileHeader;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Content_Content.jsx.html b/docs/components_MainProfile_Profile_MainContent_Content_Content.jsx.html new file mode 100644 index 00000000..88c778fc --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Content_Content.jsx.html @@ -0,0 +1,132 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Content/Content.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Content/Content.jsx

+ + + + + + +
+
+
import SignalCellularAltOutlinedIcon from '@mui/icons-material/SignalCellularAltOutlined';
+import { useLocation, useParams } from 'react-router-dom';
+import { useEffect, useState, useMemo } from 'react';
+// import InfiniteScroll from 'react-infinite-scroll-component';
+import mergeTwo from '../../../../../utils/mergeSort';
+import EmptyContent from '../../../EmptyContent/EmptyContent';
+import Filter from '../Filter/Filter';
+import { NEW, NewBox } from '../styles';
+import ContentBox from './styles';
+import Posts from '../../../Posts/Posts';
+import Comments from '../../../Comments/Comments';
+import { overviewServer } from '../../../profileServer';
+// import { useListingContext } from '../../../../../contexts/ListingContext';
+
+function useQuery() {
+  const { search } = useLocation();
+
+  return useMemo(() => new URLSearchParams(search), [search]);
+}
+
+/**
+ * Content component display the comments and posts in the profile page
+ *
+ * @component Content
+ * @property {array} posts -array of posts objects
+ * @property {array} comments -array of comments objects
+ * @property {string} username
+ * @returns {React.Component} Content
+ */
+function Content() {
+  const { username } = useParams();
+  const [isContent, setIsContent] = useState(false);
+  const query = useQuery();
+  const sort = query.get('sort');
+  const [posts, comments] = overviewServer(username, sort);
+
+  // const { setPage } = useListingContext();
+  // const fetchMoreData = () => {
+  //   setPage((page) => page + 1);
+  // };
+
+  useEffect(() => {
+    console.log(posts);
+    setIsContent(false);
+    if (posts?.length > 0 || comments?.length > 0) { setIsContent(true); }
+  }, [username, posts, comments, sort]);
+
+  const emptyContent = `hmm... u/${username}
+          hasn't posted recently`;
+
+  return (
+    <ContentBox>
+      <Filter subTitle2="./" />
+      {!isContent && <EmptyContent emptyContent={emptyContent} />}
+      {isContent
+          && (
+          <>
+            <NEW>
+              <NewBox>
+                NEW! Now you can get data and insights on your posts
+                <SignalCellularAltOutlinedIcon sx={{ color: '#b279ff' }} />
+              </NewBox>
+            </NEW>
+            {/* <InfiniteScroll
+              next={fetchMoreData}
+              hasMore
+              dataLength={posts.length}
+            > */}
+              {mergeTwo(posts, comments, sort).map((entity, index) => (
+                (!entity.comments) ? <Posts key={`${index + 0}`} post={entity} condition="true" profile />
+                  : (entity.author.name === username) ? <Posts key={`${index + 0}`} post={entity} condition="false" profile />
+                    : <Comments key={`${index + 0}`} entity={entity} overview="true" profile />
+              ))}
+            {/* </InfiniteScroll> */}
+          </>
+          )}
+    </ContentBox>
+  );
+}
+
+export default Content;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Filter_Filter.jsx.html b/docs/components_MainProfile_Profile_MainContent_Filter_Filter.jsx.html new file mode 100644 index 00000000..03656c29 --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Filter_Filter.jsx.html @@ -0,0 +1,73 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Filter/Filter.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Filter/Filter.jsx

+ + + + + + +
+
+
import FilterFull from './FilterFull/FilterFull';
+import FilterSmall from './FilterSmall/FilterSmall';
+import { FilterBox } from './styles';
+
+/**
+ * Navbar to filter posts by their category
+ *
+ * @component Filter
+ * @property {string} subTitle - title of page should navigate to
+ * @returns {React.Component} Filter
+ */
+function Filter(props) {
+  const { subTitle2 } = props;
+  return (
+    <FilterBox>
+      <FilterSmall subTitle2={subTitle2} />
+      <FilterFull subTitle2={subTitle2} />
+    </FilterBox>
+  );
+}
+
+export default Filter;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Filter_FilterFull_FilterFull.jsx.html b/docs/components_MainProfile_Profile_MainContent_Filter_FilterFull_FilterFull.jsx.html new file mode 100644 index 00000000..3d6167a9 --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Filter_FilterFull_FilterFull.jsx.html @@ -0,0 +1,167 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Filter/FilterFull/FilterFull.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Filter/FilterFull/FilterFull.jsx

+ + + + + + +
+
+
import { useState, useMemo } from 'react';
+import { useLocation, useNavigate, useParams } from 'react-router-dom';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+
+// filled
+import NewReleasesIcon from '@mui/icons-material/NewReleases';
+import LocalFireDepartmentIcon from '@mui/icons-material/LocalFireDepartment';
+import CloudUploadIcon from '@mui/icons-material/CloudUpload';
+
+// outlined
+import NewReleasesOutlinedIcon from '@mui/icons-material/NewReleasesOutlined';
+import LocalFireDepartmentOutlinedIcon from '@mui/icons-material/LocalFireDepartmentOutlined';
+import CloudUploadOutlinedIcon from '@mui/icons-material/CloudUploadOutlined';
+import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
+import {
+  FilteButton, FilterFullBox, SelectBox, SelectItem,
+} from '../styles';
+
+function useQuery() {
+  const { search } = useLocation();
+
+  return useMemo(() => new URLSearchParams(search), [search]);
+}
+
+/**
+ * filter posts by their type for large screens
+ *
+ * @component FilterFull
+ * @property {string} subTitle -subTitle of page the user is currently in
+ * @returns {React.Component} FilterFull
+ */
+function FilterFull(props) {
+  const { subTitle2 } = props;
+  const query = useQuery();
+  const sort = query.get('sort');
+  const navigate = useNavigate();
+  const newCondition = (sort === 'new');
+  const hotCondition = (sort === 'hot');
+  const topCondition = (sort === 'top' || sort === 'top&t=day');
+  const [showList, setShowList] = useState(false);
+  const [allTime, setAllTime] = useState('All Time');
+  const { username } = useParams();
+
+  // navigate
+  const handleClick = (subPage) => {
+    setAllTime('All Time');
+    navigate(`/user/${username}/${subTitle2}?sort=${subPage}`);
+  };
+  const handleClick2 = () => {
+    setAllTime('Today');
+    navigate(`/user/${username}/${subTitle2}?sort=top&t=day`);
+  };
+  const handleClickList = () => {
+    setShowList((prev) => !prev);
+  };
+
+  const handleClickAway = () => {
+    setShowList(false);
+  };
+  return (
+    <FilterFullBox>
+      <FilteButton
+        startIcon={(newCondition || (!hotCondition && !topCondition)) ? <NewReleasesIcon /> : <NewReleasesOutlinedIcon />}
+        condition={(newCondition || (!hotCondition && !topCondition)).toString()}
+        onClick={() => { handleClick('new'); }}
+      >
+        New
+      </FilteButton>
+
+      <FilteButton
+        startIcon={hotCondition ? <LocalFireDepartmentIcon /> : <LocalFireDepartmentOutlinedIcon />}
+        condition={hotCondition.toString()}
+        onClick={() => { handleClick('hot'); }}
+      >
+        Hot
+      </FilteButton>
+
+      <FilteButton
+        startIcon={topCondition ? <CloudUploadIcon /> : <CloudUploadOutlinedIcon />}
+        condition={topCondition.toString()}
+        onClick={() => { handleClick('top'); }}
+      >
+        Top
+      </FilteButton>
+      {
+          topCondition && (
+            <FilteButton
+              endIcon={<KeyboardArrowDownOutlinedIcon />}
+              condition={true.toString()}
+              onClick={() => { handleClickList(); }}
+            >
+              {allTime}
+                {showList && (
+                <ClickAwayListener onClickAway={handleClickAway}>
+                  <SelectBox>
+                    <SelectItem
+                      color="inherit"
+                      onClick={() => { handleClick2(); }}
+                      condition={(sort === 'top&t=day').toString()}
+                    >
+                      Today
+
+                    </SelectItem>
+                  </SelectBox>
+                </ClickAwayListener>
+                )}
+            </FilteButton>
+
+          )
+        }
+
+    </FilterFullBox>
+  );
+}
+
+export default FilterFull;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Filter_FilterSmall_FilterSmall.jsx.html b/docs/components_MainProfile_Profile_MainContent_Filter_FilterSmall_FilterSmall.jsx.html new file mode 100644 index 00000000..ea01788a --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Filter_FilterSmall_FilterSmall.jsx.html @@ -0,0 +1,256 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Filter/FilterSmall/FilterSmall.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Filter/FilterSmall/FilterSmall.jsx

+ + + + + + +
+
+
// outlined
+import NewReleasesOutlinedIcon from '@mui/icons-material/NewReleasesOutlined';
+import LocalFireDepartmentOutlinedIcon from '@mui/icons-material/LocalFireDepartmentOutlined';
+import CloudUploadOutlinedIcon from '@mui/icons-material/CloudUploadOutlined';
+import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
+import { useLocation, useNavigate, useParams } from 'react-router-dom';
+import { ClickAwayListener } from '@mui/material';
+import { useState, useMemo } from 'react';
+import {
+  FilteButton, FilterSmallBox, SelectBox, SelectItem,
+} from '../styles';
+
+// choose to render one of the new - hot - top buttons in smaller screens
+const renderSwitch = (
+  newCondition,
+  hotCondition,
+  topCondition,
+  handleClickList,
+  handleClickList2,
+  showList2,
+  handleClick2,
+  handleClickAway2,
+  sort,
+  allTime,
+) => {
+  if (newCondition) {
+    return (
+      <FilteButton
+        startIcon={<NewReleasesOutlinedIcon />}
+        condition="true"
+        onClick={() => { handleClickList(); }}
+        endIcon={<KeyboardArrowDownOutlinedIcon />}
+        data-testid="new-btn"
+      >
+        New
+      </FilteButton>
+    );
+  }
+
+  if (hotCondition) {
+    return (
+      <FilteButton
+        startIcon={<LocalFireDepartmentOutlinedIcon />}
+        condition="true"
+        onClick={() => { handleClickList(); }}
+        endIcon={<KeyboardArrowDownOutlinedIcon />}
+      >
+        Hot
+      </FilteButton>
+    );
+  }
+  if (topCondition) {
+    // top and all time button and its show more menu
+    return (
+      <>
+        <FilteButton
+          startIcon={<CloudUploadOutlinedIcon />}
+          condition="true"
+          onClick={() => { handleClickList(); }}
+          endIcon={<KeyboardArrowDownOutlinedIcon />}
+        >
+          Top
+        </FilteButton>
+        <FilteButton
+          endIcon={<KeyboardArrowDownOutlinedIcon />}
+          condition="true"
+          onClick={() => { handleClickList2(); }}
+        >
+          {allTime}
+          {showList2 && (
+            <ClickAwayListener onClickAway={handleClickAway2}>
+              <SelectBox>
+                <SelectItem
+                  color="inherit"
+                  onClick={() => { handleClick2(); }}
+                  condition={(sort === 'top&t=day').toString()}
+                >
+                  Today
+
+                </SelectItem>
+              </SelectBox>
+            </ClickAwayListener>
+          )}
+        </FilteButton>
+      </>
+    );
+  }
+  return (
+    <div />
+  );
+};
+
+function useQuery() {
+  const { search } = useLocation();
+
+  return useMemo(() => new URLSearchParams(search), [search]);
+}
+
+/**
+ * Filter the posts by type for small screens
+ *
+ * @component FilterSmall
+ * @property {string} subTitle -subTitle of page the user is currently in
+ * @returns {React.Component} FilterSmall
+ */
+
+function FilterSmall(props) {
+  const { subTitle2 } = props;
+  const query = useQuery();
+  const sort = query.get('sort');
+  const navigate = useNavigate();
+  // check the url of the page i m currently in
+  const hotCondition = (sort === 'hot');
+  const topCondition = (sort === 'top' || sort === 'top&t=day');
+  // new by default
+  const newCondition = !hotCondition && !topCondition;
+  const [showList, setShowList] = useState(false);
+  const [showList2, setShowList2] = useState(false);
+  const [allTime, setAllTime] = useState('All Time');
+  const { username } = useParams();
+
+  const handleClick = (subPage) => {
+    setAllTime('All Time');
+    navigate(`/user/${username}/${subTitle2}?sort=${subPage}`);
+  };
+  const handleClick2 = () => {
+    setAllTime('Today');
+    navigate(`/user/${username}/${subTitle2}?sort=top&t=day`);
+  };
+
+  // show list of new - hot - top
+  const handleClickList = () => {
+    setShowList((prev) => !prev);
+  };
+
+  const handleClickAway = () => {
+    setShowList(false);
+  };
+
+  // show list of all time
+  const handleClickList2 = () => {
+    setShowList2((prev) => !prev);
+  };
+
+  const handleClickAway2 = () => {
+    setShowList2(false);
+  };
+
+  const content = [
+    {
+      id: 1, text: 'New', nav: 'new', icon: <NewReleasesOutlinedIcon />, condition: !hotCondition && !topCondition,
+    },
+    {
+      id: 2, text: 'Hot', nav: 'hot', icon: <LocalFireDepartmentOutlinedIcon />, condition: hotCondition,
+    },
+    {
+      id: 3, text: 'Top', nav: 'top', icon: <CloudUploadOutlinedIcon />, condition: topCondition,
+    },
+  ];
+
+  return (
+    <FilterSmallBox>
+
+      {renderSwitch(
+        newCondition,
+        hotCondition,
+        topCondition,
+        handleClickList,
+        handleClickList2,
+        showList2,
+        handleClick2,
+        handleClickAway2,
+        sort,
+        allTime,
+      )}
+
+      {showList && (
+        <ClickAwayListener onClickAway={handleClickAway}>
+          <SelectBox sx={{ marginTop: -1, marginLeft: 0 }} data-testid="more-menu">
+            { content.map((entity) => (
+              <FilteButton
+                key={entity.id}
+                startIcon={entity.icon}
+                condition={(entity.condition).toString()}
+                onClick={() => { handleClick(`${entity.nav}`); }}
+                sx={{
+                  borderRadius: 0,
+                  '&:hover': {
+                    color: 'black',
+                    bgcolor: '#e9f5fd',
+                  },
+                }}
+              >
+                {entity.text}
+              </FilteButton>
+            ))}
+          </SelectBox>
+        </ClickAwayListener>
+      )}
+
+    </FilterSmallBox>
+  );
+}
+
+export default FilterSmall;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_PostsFilteredTap_PostsFilteredTap.jsx.html b/docs/components_MainProfile_Profile_MainContent_PostsFilteredTap_PostsFilteredTap.jsx.html new file mode 100644 index 00000000..c7c6b21d --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_PostsFilteredTap_PostsFilteredTap.jsx.html @@ -0,0 +1,99 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/PostsFilteredTap/PostsFilteredTap.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/PostsFilteredTap/PostsFilteredTap.jsx

+ + + + + + +
+
+
import { useContext, useEffect, useState } from 'react';
+import { useParams } from 'react-router-dom';
+// import InfiniteScroll from 'react-infinite-scroll-component';
+import renderText from '../../../../../utils/renderText';
+import { WideBox } from '../styles';
+import EmptyContent from '../../../EmptyContent/EmptyContent';
+import { UserContext } from '../../../../../contexts/UserProvider';
+import Post from '../Posts/Post';
+import postsFilteredTapServer from './postsFilteredTapServer';
+// import { useListingContext } from '../../../../../contexts/ListingContext';
+
+/**
+ * filtered taps (saved - hidden - upvoted - downvoted)
+ *
+ * @component PostsFilteredTap
+ * @property {string} type - conatins the subtitle of the page to render correctly
+ * @returns {React.Component} PostsFilteredTap
+ */
+function PostsFilteredTap() {
+  const { subTitle } = useParams();
+  const { username } = useContext(UserContext);
+  const [posts] = postsFilteredTapServer(subTitle);
+  const [isContent, setIsContent] = useState(false);
+
+  // const { setPage } = useListingContext();
+  // const fetchMoreData = () => {
+  //   setPage((page) => page + 1);
+  // };
+
+  // check if the page have any content posts to show
+  useEffect(() => {
+    setIsContent(false);
+    if (posts?.length > 0) { setIsContent(true); }
+    console.log(isContent);
+  }, [username, posts, subTitle, isContent]);
+
+  const emptyContent = renderText(subTitle);
+  return (
+    <WideBox>
+      {!isContent && <EmptyContent emptyContent={emptyContent} />}
+      {isContent && (
+        posts.map((entity, index) => (<Post key={`${index + 0}`} entity={entity} type={subTitle} />))
+      )}
+    </WideBox>
+  );
+}
+
+export default PostsFilteredTap;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_PostsTap_PostsTap.jsx.html b/docs/components_MainProfile_Profile_MainContent_PostsTap_PostsTap.jsx.html new file mode 100644 index 00000000..8dfa67f1 --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_PostsTap_PostsTap.jsx.html @@ -0,0 +1,128 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/PostsTap/PostsTap.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/PostsTap/PostsTap.jsx

+ + + + + + +
+
+
import { useLocation, useParams } from 'react-router-dom';
+import SignalCellularAltOutlinedIcon from '@mui/icons-material/SignalCellularAltOutlined';
+import {
+  useContext, useEffect, useState, useMemo,
+} from 'react';
+// import InfiniteScroll from 'react-infinite-scroll-component';
+import { postsCommentsServer } from '../../../profileServer';
+import Filter from '../Filter/Filter';
+import { NEW, NewBox, WideBox } from '../styles';
+import EmptyContent from '../../../EmptyContent/EmptyContent';
+import { UserContext } from '../../../../../contexts/UserProvider';
+import Post from '../Posts/Post';
+// import { useListingContext } from '../../../../../contexts/ListingContext';
+
+function useQuery() {
+  const { search } = useLocation();
+
+  return useMemo(() => new URLSearchParams(search), [search]);
+}
+
+/**
+ * posts tap in my profile
+ *
+ * @component PostsTap
+ * @returns {React.Component} PostsTap
+ */
+function PostsTap() {
+  const { subTitle } = useParams();
+  const query = useQuery();
+  const sort = query.get('sort');
+  const { username } = useContext(UserContext);
+  const [posts] = postsCommentsServer(username, 'posts', sort || 'new');
+  const [isContent, setIsContent] = useState(false);
+
+  // const { setPage } = useListingContext();
+  // const fetchMoreData = () => {
+  //   setPage((page) => page + 1);
+  // };
+
+  // check if the page have any content posts to show
+  useEffect(() => {
+    setIsContent(false);
+    if (posts?.length > 0) { setIsContent(true); }
+  }, [username, posts, sort]);
+
+  const emptyContent = `hmm... u/${username}
+          hasn't posted recently`;
+  return (
+    <WideBox>
+      <Filter subTitle2={`${subTitle}/`} />
+      {!isContent && <EmptyContent emptyContent={emptyContent} />}
+      {isContent
+          && (
+          <>
+            <NEW sx={{ margin: 0 }}>
+              <NewBox>
+                NEW! Now you can get data and insights on your posts
+                <SignalCellularAltOutlinedIcon sx={{ color: '#b279ff' }} />
+              </NewBox>
+            </NEW>
+            {/* {posts && (
+            <InfiniteScroll
+              next={fetchMoreData}
+              hasMore
+              dataLength={posts.length}
+            > */}
+              { posts.map((entity, index) => (<Post key={`${index + 0}`} entity={entity} />))}
+            {/* </InfiniteScroll>
+            )} */}
+          </>
+          )}
+
+    </WideBox>
+  );
+}
+
+export default PostsTap;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Posts_Post.jsx.html b/docs/components_MainProfile_Profile_MainContent_Posts_Post.jsx.html new file mode 100644 index 00000000..8cf41b54 --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Posts_Post.jsx.html @@ -0,0 +1,224 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Posts/Post.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Posts/Post.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import ArticleOutlinedIcon from '@mui/icons-material/ArticleOutlined';
+import { useState, useContext, useEffect } from 'react';
+
+import { useNavigate } from 'react-router-dom';
+import { useEditPostContext } from '../../../../../contexts/EditPostContext';
+import { CommunitiesContext } from '../../../../../contexts/CommunitiesModeratorContext';
+import {
+  EmptyImage,
+  Flair,
+  PostContentBox,
+  PostImage,
+  PostSidebaRes,
+  PostsQueueBox,
+  TagPost,
+  TitlePost,
+} from './styles';
+import PostSide from './PostSide/PostSide';
+import PostHeader from './PostHeader/PostHeader';
+import PostFooter from './PostFooter/PostFooter';
+import { UserContext } from '../../../../../contexts/UserProvider';
+import { CommunitiesSubscriberContext } from '../../../../../contexts/CommunitiesSubscriberContext';
+import { actionOnPost, moderationAction } from '../../../profileServer';
+
+/**
+ * the post that appear in posts - saved - hidden - upvoted - downvotep taps
+ *
+ * @component Post
+ * @property {object} entity - an entity conatins all post informations
+ * @property {string} type -subTitle of the page
+ * @returns {React.Component} Post
+ */
+function Post(props) {
+  const {
+    entity,
+    type,
+  } = props;
+  const [expand, setExpand] = useState();
+  const [subTitle, setSubTitle] = useState(type);
+  const [modList, setModList] = useState(false);
+  const { username } = useContext(UserContext);
+  const { communities } = useContext(CommunitiesContext);
+  const { communitiesSubscriber } = useContext(CommunitiesSubscriberContext);
+  const [notJoined, setNotJoined] = useState(false);
+
+  const [isNsfw, setIsNsfw] = useState(entity?.nsfw);
+  const [isSpoiler, setIsSpoiler] = useState(entity?.spoiler);
+  const [isLocked, setIsLocked] = useState(entity?.locked);
+  const [modState, setModState] = useState(entity?.modState);
+
+  const handleExpand = () => {
+    setExpand((prev) => !prev);
+  };
+  useEffect(() => {
+    console.log(entity?.postVoteStatus);
+    setSubTitle(type);
+    if (communitiesSubscriber?.filter((element) => element.fixedName === entity.owner.name).length === 0) {
+      setNotJoined(true);
+    }
+    if (entity.ownerType === 'Subreddit' && communities?.filter((element) => element.fixedName === entity.owner.name).length > 0) {
+      setModList(true);
+    }
+  }, [type, communities, entity, communitiesSubscriber]);
+
+  const handleNsfw = () => {
+    actionOnPost(entity?.postid, isNsfw ? 'unmark_nsfw' : 'mark_nsfw');
+    setIsNsfw((prev) => !prev);
+  };
+  const handleSpoiler = () => {
+    actionOnPost(entity?.postid, isSpoiler ? 'unspoiler' : 'spoiler');
+    setIsSpoiler((prev) => !prev);
+  };
+  const handleLock = () => {
+    actionOnPost(entity?.postid, isLocked ? 'unlock_comments' : 'lock_comments');
+    setIsLocked((prev) => !prev);
+  };
+  const handleApprove = () => {
+    moderationAction(entity?.postid, 'approve');
+    setModState('approved');
+  };
+  const handleRemove = () => {
+    moderationAction(entity?.postid, 'remove');
+    setModState('removed');
+  };
+  const handleSpam = () => {
+    moderationAction(entity?.postid, 'spam');
+    setModState('spammed');
+  };
+
+  const navigate = useNavigate();
+  const { setEditPost } = useEditPostContext();
+
+  return (
+    <PostsQueueBox saved={subTitle}>
+      <PostSide postid={entity?._id} points={entity?.votes} postVoteStatus={entity?.postVoteStatus} spam={entity?.modState === 'spam'} />
+
+      <PostSidebaRes>
+        <Box sx={{ display: 'flex' }}>
+          <EmptyImage onClick={() => { setEditPost(false); navigate(`/${entity?.ownerType === 'Subreddit' ? 'subreddit' : 'user'}/${entity?.owner?.name}/comments/${entity?._id}`); }}>
+            {entity?.images.length === 0 ? (
+
+              <ArticleOutlinedIcon fontSize="small" color="disabled" />
+            )
+              : (
+                <PostImage src={entity?.images[0]} alt="post pic" />
+
+              )}
+          </EmptyImage>
+          <PostContentBox>
+            <Box sx={{ marginLeft: 1 }}>
+              <Box sx={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }} onClick={() => { setEditPost(false); navigate(`/${entity?.ownerType === 'Subreddit' ? 'subreddit' : 'user'}/${entity?.owner?.name}/comments/${entity?._id}`); }}>
+                <TitlePost variant="h6">{entity?.title}</TitlePost>
+                {
+                  entity?.flairId?.text
+                  && (
+                  <Flair
+                    disableRipple
+                    backgroundcolor={entity?.flairId?.backgroundColor}
+                    flaircolor={entity?.flairId?.textColor}
+                  >
+                    {entity?.flairId?.text}
+                  </Flair>
+                  )
+                }
+                {isSpoiler && <TagPost color="#A4A7A8" variant="caption">spoiler</TagPost>}
+                {isNsfw && <TagPost color="#FF585B" variant="caption">nsfw</TagPost>}
+              </Box>
+              <PostHeader
+                subReddit={entity?.owner.name}
+                type={entity?.ownerType}
+                nameUser={entity?.author.name}
+                Time={entity?.createdAt}
+                locked={isLocked}
+                modState={modState}
+                notJoined={notJoined}
+                sharedFrom={entity?.sharedFrom}
+              />
+              <PostFooter
+                postid={entity?._id}
+                ownerType={entity?.ownerType}
+                owner={entity?.owner?.name}
+                handleExpand={handleExpand}
+                expand={expand}
+                submitted={subTitle === undefined}
+                isModList={modList}
+                postedByOthers={(entity?.author.name !== username)}
+                saved={entity?.isSaved}
+                hidden={entity?.isHidden}
+                numComments={entity?.commentCount}
+                points={entity?.votes}
+                postVoteStatus={entity?.postVoteStatus}
+                sendReplies={entity?.sendReplies}
+                nsfw={isNsfw}
+                spoiler={isSpoiler}
+                locked={isLocked}
+                modState={modState}
+                handleLock={handleLock}
+                handleSpoiler={handleSpoiler}
+                handleNsfw={handleNsfw}
+                handleApprove={handleApprove}
+                handleRemove={handleRemove}
+                handleSpam={handleSpam}
+              />
+            </Box>
+          </PostContentBox>
+        </Box>
+        {expand && <Box dangerouslySetInnerHTML={{ __html: entity?.text }} />}
+      </PostSidebaRes>
+    </PostsQueueBox>
+  );
+}
+
+export default Post;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Posts_PostFooter_ArrowList_ArrowList.jsx.html b/docs/components_MainProfile_Profile_MainContent_Posts_PostFooter_ArrowList_ArrowList.jsx.html new file mode 100644 index 00000000..67d688d4 --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Posts_PostFooter_ArrowList_ArrowList.jsx.html @@ -0,0 +1,109 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Posts/PostFooter/ArrowList/ArrowList.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Posts/PostFooter/ArrowList/ArrowList.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+import {
+  DownArrow,
+  DownArrowFilled,
+  Number, UpArrow, UpArrowFilled, Votes,
+} from './styles';
+import { postReactionsServer } from '../../../../../profileServer';
+
+/**
+ * the upvoted and downvoted arrows in responsive postfooter
+ *
+ * @component ArrowList
+ * @property {number} points - get number of upvotes or downvotes on a post
+ * @property {number} postVoteStatus - get if the post is upvoted or downvoted or none
+ * @returns {React.Component} ArrowList
+ */
+function ArrowList(props) {
+  const { postid, points, postVoteStatus } = props;
+  const [postPoints, setPostPoints] = useState(points);
+  const [status, setStatus] = useState(postVoteStatus);
+
+  const handleClickUp = () => {
+    postReactionsServer(postid, 'vote', 1);
+    if (status === '-1') setPostPoints(postPoints + 2);
+    else setPostPoints(postPoints + 1);
+    setStatus('1');
+  };
+  const handleClickDown = () => {
+    postReactionsServer(postid, 'vote', -1);
+    if (status === '1') setPostPoints(postPoints - 2);
+    else setPostPoints(postPoints - 1);
+    setStatus('-1');
+  };
+  const handleNoUpvote = () => {
+    postReactionsServer(postid, 'vote', 0);
+    setPostPoints(postPoints - 1);
+    setStatus('0');
+  };
+  const handleNoDownvote = () => {
+    postReactionsServer(postid, 'vote', 0);
+    setPostPoints(postPoints + 1);
+    setStatus('0');
+  };
+
+  return (
+    <Votes>
+      {
+        (status === '1') ? <UpArrowFilled onClick={() => { handleNoUpvote(); }} /> : <UpArrow onClick={() => { handleClickUp(); }} />
+      }
+      <Number variant="caption" sx={{ fontWeight: 700 }}>{postPoints}</Number>
+      {
+        (status === '-1') ? <DownArrowFilled onClick={() => { handleNoDownvote(); }} /> : <DownArrow onClick={() => { handleClickDown(); }} />
+      }
+    </Votes>
+  );
+}
+
+export default ArrowList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Posts_PostFooter_PostFooter.jsx.html b/docs/components_MainProfile_Profile_MainContent_Posts_PostFooter_PostFooter.jsx.html new file mode 100644 index 00000000..bef09f85 --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Posts_PostFooter_PostFooter.jsx.html @@ -0,0 +1,316 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Posts/PostFooter/PostFooter.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Posts/PostFooter/PostFooter.jsx

+ + + + + + +
+
+
import ChatBubbleOutlineOutlinedIcon from '@mui/icons-material/ChatBubbleOutlineOutlined';
+import ShortcutOutlinedIcon from '@mui/icons-material/ShortcutOutlined';
+import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined';
+import BlockOutlinedIcon from '@mui/icons-material/BlockOutlined';
+import AdminPanelSettingsOutlinedIcon from '@mui/icons-material/AdminPanelSettingsOutlined';
+import MoreHorizOutlinedIcon from '@mui/icons-material/MoreHorizOutlined';
+import CancelPresentationOutlinedIcon from '@mui/icons-material/CancelPresentationOutlined';
+import SignalCellularAltOutlinedIcon from '@mui/icons-material/SignalCellularAltOutlined';
+import ModeEditOutlinedIcon from '@mui/icons-material/ModeEditOutlined';
+import { useEffect, useState } from 'react';
+import { ClickAwayListener, Divider } from '@mui/material';
+
+import BookmarkBorderOutlinedIcon from '@mui/icons-material/BookmarkBorderOutlined';
+import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
+import UnfoldLessOutlinedIcon from '@mui/icons-material/UnfoldLessOutlined';
+import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined';
+import FlagOutlinedIcon from '@mui/icons-material/FlagOutlined';
+import BookmarksOutlinedIcon from '@mui/icons-material/BookmarksOutlined';
+import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
+import { useNavigate } from 'react-router-dom';
+import {
+  ElementBox, FooterBox, FooterText,
+} from './styles';
+import PostFooterList from './PostFooterList/PostFooterList';
+import PostFooterListResponsive from './PostFooterListResponsive/PostFooterListResponsive';
+import ArrowList from './ArrowList/ArrowList';
+import { postReactionsServer } from '../../../../profileServer';
+import ModeratorList from '../../../../ModeratorList/ModeratorList';
+import { useEditPostContext } from '../../../../../../contexts/EditPostContext';
+
+/**
+ * Footer of the post that contain all icons
+ *
+ * @component PostFooter
+ * @property {function} handleExpand - pass the event to the parent to show the paragraph of the post
+ * @property {state} expand - pass a state to the parent to change the icon
+ * @property {object} entity - contains all info of the post
+ * @returns {React.Component} PostFooter
+ */
+function PostFooter(props) {
+  const {
+    postid, numComments, modState, handleExpand, expand, postedByOthers,
+    saved, hidden, submitted, isModList, points, postVoteStatus, nsfw, spoiler, sendReplies, locked,
+    handleLock, handleSpoiler, handleNsfw, handleApprove, handleRemove, handleSpam,
+    ownerType, owner,
+  } = props;
+  const [isHidden, setIsHidden] = useState(hidden);
+  const [isSaved, setIsSaved] = useState(saved);
+  const [showList, setShowList] = useState(false);
+  const [showList2, setShowList2] = useState(false);
+  const [moderatorList, setModeratorList] = useState(false);
+  const [modList, setModList] = useState(false);
+
+  const navigate = useNavigate();
+  const { setEditPost, setCommentPost } = useEditPostContext();
+
+  // handle disable the list when click away
+  const handleClick = () => {
+    setShowList((prev) => !prev);
+  };
+
+  const handleClickAway = () => {
+    setShowList(false);
+  };
+
+  const handleClickAway2 = () => {
+    setShowList2(false);
+  };
+
+  // handle disable the list when click away
+  const handleClick2 = () => {
+    setShowList2((prev) => !prev);
+  };
+
+  const handleModList = () => {
+    setModeratorList((prev) => !prev);
+  };
+
+  const handleModListClickAway = () => {
+    setModeratorList(false);
+  };
+
+  // switch icon to hidden post and vice verse
+  const handleClickHide = () => {
+    postReactionsServer(postid, isHidden ? 'unhide' : 'hide', isHidden);
+    setIsHidden((prev) => !prev);
+  };
+
+  // switch icon to saved post and vice versa
+  const handleClickSave = () => {
+    postReactionsServer(postid, isSaved ? 'unsave' : 'save', isSaved);
+    setIsSaved((prev) => !prev);
+  };
+
+  const handleEditPost = () => {
+    setEditPost(true);
+    navigate(`/${ownerType === 'Subreddit' ? 'r' : 'user'}/${owner}/comments/${postid}`);
+  };
+
+  useEffect(() => {
+    setIsSaved(saved);
+    setIsHidden(hidden);
+    setModList(isModList);
+  }, [saved, hidden, isModList, modList]);
+
+  const handleShare = () => {
+    navigate(`/submit/${postid}`);
+  };
+
+  const moderator = [
+    {
+      id: 1, text: 'Approved', condition: modState === 'approved', icon: <CheckCircleOutlineOutlinedIcon />, func: handleApprove,
+    },
+    {
+      id: 2, text: 'Removed', condition: modState === 'removed', icon: <BlockOutlinedIcon />, func: handleRemove,
+    },
+    {
+      id: 3, text: 'Spam', condition: modState === 'spammed', icon: <CancelPresentationOutlinedIcon />, func: handleSpam,
+    },
+  ];
+  const common = [
+    isSaved ? {
+      id: 1, text: 'Unsave', icon: <BookmarksOutlinedIcon />, func: handleClickSave,
+    } : {
+      id: 1, text: 'Save', icon: <BookmarkBorderOutlinedIcon />, func: handleClickSave,
+    },
+    isHidden ? {
+      id: 2, text: 'Unhide', icon: <VisibilityOffIcon />, func: handleClickHide,
+    } : {
+      id: 2, text: 'Hide', icon: <VisibilityOffOutlinedIcon />, func: handleClickHide,
+    },
+  ];
+
+  return (
+    <FooterBox>
+      <ArrowList postid={postid} points={points} postVoteStatus={postVoteStatus} />
+      <ElementBox>
+        {expand ? <UnfoldLessOutlinedIcon sx={{ rotate: '-45deg' }} onClick={() => { handleExpand(); }} />
+          : <UnfoldMoreOutlinedIcon sx={{ rotate: '-45deg' }} onClick={() => { handleExpand(); }} />}
+      </ElementBox>
+      <Divider orientation="vertical" variant="middle" flexItem />
+
+      <ElementBox onClick={() => { setCommentPost(true); setEditPost(false); navigate(`/${ownerType === 'Subreddit' ? 'r' : 'user'}/${owner}/comments/${postid}`); }}>
+        <ChatBubbleOutlineOutlinedIcon />
+        <FooterText variant="caption" responsiveshare={true.toString()}>
+          {numComments}
+          {!submitted && ' Comments'}
+        </FooterText>
+      </ElementBox>
+
+      <ElementBox onClick={handleShare}>
+        <ShortcutOutlinedIcon />
+        <FooterText variant="caption" responsiveshare={true.toString()}>Share</FooterText>
+      </ElementBox>
+
+      {(!postedByOthers && (!modList || !submitted)) && (
+        <ElementBox awardedit={true.toString()}>
+          <ModeEditOutlinedIcon />
+          <FooterText
+            variant="caption"
+            responsiveshare={true.toString()}
+            onClick={handleEditPost}
+          >
+            Edit Post
+          </FooterText>
+        </ElementBox>
+      )}
+
+      {(!modList || !submitted) && (
+        <>
+          {common.map((entity) => (
+            <ElementBox
+              key={entity.id}
+              onClick={() => { entity.func(); }}
+              data-testid={(entity.id === 2) && 'hidden'}
+              condition={true.toString()}
+            >
+              {entity.icon}
+              <FooterText variant="caption" condition={true.toString()} data-testid={(entity.id === 2) && 'text-hide'}>{entity.text}</FooterText>
+            </ElementBox>
+          ))}
+        </>
+      )}
+
+      {(submitted && modList) && moderator.map((entity) => (
+        <ElementBox
+          key={entity.id}
+          approved={(entity.condition && entity.text === 'Approved')?.toString()}
+          spam={(entity.condition && (entity.text === 'Spam' || entity.text === 'Removed'))?.toString()}
+          modicons={true.toString()}
+          onClick={entity.func}
+        >
+          {entity.icon}
+          <FooterText variant="caption" condition={true.toString()}>{entity.text}</FooterText>
+        </ElementBox>
+      ))}
+
+      {(submitted && modList) && (
+        <ClickAwayListener onClickAway={handleModListClickAway}>
+          <ElementBox>
+            <AdminPanelSettingsOutlinedIcon onClick={handleModList} />
+            {moderatorList && (
+              <ModeratorList
+                postid={postid}
+                nsfw={nsfw}
+                spoiler={spoiler}
+                locked={locked}
+                handleNsfw={handleNsfw}
+                handleSpoiler={handleSpoiler}
+                handleLock={handleLock}
+              />
+            )}
+          </ElementBox>
+        </ClickAwayListener>
+      )}
+
+      {(submitted) && (
+        <ElementBox condition2={true.toString()}>
+          <SignalCellularAltOutlinedIcon sx={{ color: '#b279ff' }} />
+          <FooterText variant="caption">Insights</FooterText>
+        </ElementBox>
+      )}
+
+      {postedByOthers ? (
+        <ElementBox condition={true.toString()}>
+          <FlagOutlinedIcon />
+          <FooterText variant="caption" condition={true.toString()}>Report</FooterText>
+        </ElementBox>
+      ) : (
+        <ClickAwayListener onClickAway={handleClickAway}>
+          <ElementBox>
+            <MoreHorizOutlinedIcon onClick={handleClick} />
+            {showList && (
+              <PostFooterList
+                postid={postid}
+                handleEditPost={handleEditPost}
+                isSaved={saved}
+                nsfw={nsfw}
+                spoiler={spoiler}
+                sendReplies={sendReplies}
+                handleNsfw={handleNsfw}
+                handleSpoiler={handleSpoiler}
+              />
+            )}
+          </ElementBox>
+        </ClickAwayListener>
+      )}
+
+      {postedByOthers && (
+        <ClickAwayListener onClickAway={handleClickAway2}>
+          <ElementBox show={true.toString()}>
+            <MoreHorizOutlinedIcon onClick={handleClick2} />
+            {showList2 && (
+              <PostFooterListResponsive postid={postid} isSaved={isSaved} />
+            )}
+          </ElementBox>
+        </ClickAwayListener>
+
+      )}
+
+    </FooterBox>
+  );
+}
+
+export default PostFooter;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Posts_PostFooter_PostFooterListResponsive_PostFooterListResponsive.jsx.html b/docs/components_MainProfile_Profile_MainContent_Posts_PostFooter_PostFooterListResponsive_PostFooterListResponsive.jsx.html new file mode 100644 index 00000000..86e1d122 --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Posts_PostFooter_PostFooterListResponsive_PostFooterListResponsive.jsx.html @@ -0,0 +1,106 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Posts/PostFooter/PostFooterListResponsive/PostFooterListResponsive.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Posts/PostFooter/PostFooterListResponsive/PostFooterListResponsive.jsx

+ + + + + + +
+
+
import BookmarkBorderOutlinedIcon from '@mui/icons-material/BookmarkBorderOutlined';
+import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined'; import BookmarksOutlinedIcon from '@mui/icons-material/BookmarksOutlined';
+import FlagOutlinedIcon from '@mui/icons-material/FlagOutlined';
+
+import { Divider } from '@mui/material';
+import { useState } from 'react';
+import { SelectBox, SelectItem } from './styles';
+import { postReactionsServer } from '../../../../../profileServer';
+
+/**
+ * resposive list of the post footer
+ *
+ * @component PostFooterListResponsive
+ * @returns {React.Component} PostFooterListResponsive
+ */
+function PostFooterListResponsive(props) {
+  const { postid, isSaved } = props;
+  const [saved, setSaved] = useState(isSaved);
+  const handleSave = () => {
+    postReactionsServer(postid, saved ? 'unsave' : 'save', saved);
+    setSaved((prev) => !prev);
+  };
+  const handleHide = () => {
+    postReactionsServer(postid, 'hide', 1);
+  };
+  return (
+    <SelectBox>
+
+      {!saved ? (
+        <SelectItem onClick={() => { handleSave(); }}>
+          <BookmarkBorderOutlinedIcon sx={{ marginRight: 1 }} />
+          Save
+        </SelectItem>
+      )
+        : (
+          <SelectItem condition={true.toString()} onClick={() => { handleSave(); }}>
+            <BookmarksOutlinedIcon sx={{ marginRight: 1 }} />
+            Unsave
+          </SelectItem>
+        )}
+      <Divider />
+      <SelectItem onClick={() => { handleHide(); }}>
+        <VisibilityOffOutlinedIcon sx={{ marginRight: 1 }} />
+        Hide
+      </SelectItem>
+      <Divider />
+      <SelectItem>
+        <FlagOutlinedIcon sx={{ marginRight: 1 }} />
+        Report
+      </SelectItem>
+    </SelectBox>
+  );
+}
+
+export default PostFooterListResponsive;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Posts_PostFooter_PostFooterList_PostFooterList.jsx.html b/docs/components_MainProfile_Profile_MainContent_Posts_PostFooter_PostFooterList_PostFooterList.jsx.html new file mode 100644 index 00000000..ea906b38 --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Posts_PostFooter_PostFooterList_PostFooterList.jsx.html @@ -0,0 +1,177 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Posts/PostFooter/PostFooterList/PostFooterList.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Posts/PostFooter/PostFooterList/PostFooterList.jsx

+ + + + + + +
+
+
import DeleteOutlineOutlinedIcon from '@mui/icons-material/DeleteOutlineOutlined';
+import CropSquareOutlinedIcon from '@mui/icons-material/CropSquareOutlined';
+import PushPinOutlinedIcon from '@mui/icons-material/PushPinOutlined';
+import BookmarkBorderOutlinedIcon from '@mui/icons-material/BookmarkBorderOutlined';
+import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
+import ModeEditOutlinedIcon from '@mui/icons-material/ModeEditOutlined';
+import BookmarksOutlinedIcon from '@mui/icons-material/BookmarksOutlined';
+import CheckBoxIcon from '@mui/icons-material/CheckBox';
+import { Divider } from '@mui/material';
+import { useState } from 'react';
+import { SelectBox, SelectItem } from './styles';
+import { deletePostComment, postReactionsServer } from '../../../../../profileServer';
+
+/**
+ * List items of post footer
+ *
+ * @component PostFooterList
+ * @returns {React.Component} PostFooterList
+ */
+function PostFooterList(props) {
+  const {
+    postid,
+    handleEditPost,
+    isSaved,
+    nsfw,
+    spoiler,
+    sendReplies,
+    handleNsfw,
+    handleSpoiler,
+  } = props;
+  const [saved, setSaved] = useState(isSaved);
+  const [isSendReplies, setIsSendReplies] = useState(sendReplies);
+
+  const handleSave = () => {
+    postReactionsServer(postid, saved ? 'unsave' : 'save', saved);
+    setSaved((prev) => !prev);
+  };
+  const handleHide = () => {
+    postReactionsServer(postid, 'hide', 1);
+  };
+
+  const handleSendReplies = () => {
+    setIsSendReplies((prev) => !prev);
+  };
+  const handleDelete = () => {
+    deletePostComment('posts', postid);
+  };
+  return (
+    <SelectBox>
+      <SelectItem onClick={handleEditPost}>
+        <ModeEditOutlinedIcon sx={{ marginRight: 1 }} />
+        Edit Post
+      </SelectItem>
+      <Divider />
+      {!saved ? (
+        <SelectItem onClick={() => { handleSave(); }}>
+          <BookmarkBorderOutlinedIcon sx={{ marginRight: 1 }} />
+          Save
+        </SelectItem>
+      )
+        : (
+          <SelectItem condition={true.toString()} onClick={() => { handleSave(); }}>
+            <BookmarksOutlinedIcon sx={{ marginRight: 1 }} />
+            Unsave
+          </SelectItem>
+        )}
+      <Divider />
+      <SelectItem>
+        <PushPinOutlinedIcon sx={{ marginRight: 1 }} />
+        Pin Post To Profile
+      </SelectItem>
+      <Divider />
+      <SelectItem onClick={() => { handleHide(); }}>
+        <VisibilityOffOutlinedIcon sx={{ marginRight: 1 }} />
+        Hide
+      </SelectItem>
+      <Divider />
+      <SelectItem onClick={() => { handleDelete(); }}>
+        <DeleteOutlineOutlinedIcon sx={{ marginRight: 1 }} />
+        Delete
+      </SelectItem>
+      <Divider />
+      {!spoiler ? (
+        <SelectItem onClick={handleSpoiler}>
+          <CropSquareOutlinedIcon sx={{ marginRight: 1 }} />
+          Mark As Spoiler
+        </SelectItem>
+      )
+        : (
+          <SelectItem onClick={handleSpoiler}>
+            <CheckBoxIcon sx={{ marginRight: 1 }} />
+            Mark As Spoiler
+          </SelectItem>
+        )}
+      <Divider />
+      {!nsfw ? (
+        <SelectItem onClick={handleNsfw}>
+          <CropSquareOutlinedIcon sx={{ marginRight: 1 }} />
+          Mark As NSFW
+        </SelectItem>
+      )
+        : (
+          <SelectItem onClick={handleNsfw}>
+            <CheckBoxIcon sx={{ marginRight: 1 }} />
+            Mark As NSFW
+          </SelectItem>
+        )}
+
+      <Divider />
+      {!isSendReplies ? (
+        <SelectItem onClick={() => { handleSendReplies(); }}>
+          <CropSquareOutlinedIcon sx={{ marginRight: 1 }} />
+          Send Me Reply Notifications
+        </SelectItem>
+      ) : (
+        <SelectItem onClick={() => { handleSendReplies(); }}>
+          <CheckBoxIcon sx={{ marginRight: 1 }} />
+          Send Me Reply Notifications
+        </SelectItem>
+      )}
+
+    </SelectBox>
+  );
+}
+
+export default PostFooterList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Posts_PostHeader_PostHeader.jsx.html b/docs/components_MainProfile_Profile_MainContent_Posts_PostHeader_PostHeader.jsx.html new file mode 100644 index 00000000..854929b7 --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Posts_PostHeader_PostHeader.jsx.html @@ -0,0 +1,160 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Posts/PostHeader/PostHeader.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Posts/PostHeader/PostHeader.jsx

+ + + + + + +
+
+
import { Typography } from '@mui/material';
+
+import LockIcon from '@mui/icons-material/Lock';
+import Inventory2Icon from '@mui/icons-material/Inventory2';
+import DoDisturbAltIcon from '@mui/icons-material/DoDisturbAlt';
+import CheckCircleIcon from '@mui/icons-material/CheckCircle';
+import moment from 'moment/moment';
+import CallSplitIcon from '@mui/icons-material/CallSplit';
+import { useState } from 'react';
+import {
+  HeaderPost, Joined, LinkCross, LinkTo,
+} from './styles';
+
+/**
+ * Header of the post
+ *
+ * @component PostHeader
+ * @property {string} nameUser -name of the currently loggedin user
+ * @property {string} Time -contains the time of the post
+ * @property {string} nameUser -contains the name of subreddit the post piblished in
+ * @returns {React.Component} PostHeader
+ */
+
+function PostHeader(props) {
+  const {
+    nameUser,
+    Time,
+    subReddit,
+    type,
+    notJoined,
+    modState,
+    locked,
+    sharedFrom,
+  } = props;
+
+  const [joined, setJoined] = useState(false);
+
+  const handleJoin = () => {
+    setJoined((prev) => !prev);
+  };
+
+  const [hover, setHover] = useState(false);
+
+  const handleMouseIn = () => {
+    setHover(true);
+  };
+  const handleMouseOut = () => {
+    setHover(false);
+  };
+  return (
+    <HeaderPost>
+
+      <LinkTo to={(type === 'Subreddit') ? `/r/${subReddit}` : `/user/${subReddit}`}>
+        <Typography variant="caption" sx={{ fontWeight: 700, '&:hover': { textDecoration: 'underline' } }}>
+          {type === 'Subreddit' ? 'r/' : 'u/'}
+          {subReddit}
+          {' '}
+          .
+        </Typography>
+      </LinkTo>
+      {(notJoined && type === 'Subreddit') && (
+      <Joined
+        variant={(joined ? 'outlined' : 'contained')}
+        onClick={handleJoin}
+        onMouseEnter={handleMouseIn}
+        onMouseLeave={handleMouseOut}
+        data-testid="join button"
+      >
+        {(joined ? (hover ? 'leave' : 'joined') : 'join')}
+      </Joined>
+      )}
+
+      <Typography variant="caption" sx={{ color: '#787c7e', marginLeft: 1 }}>
+        Posted by
+      </Typography>
+      <LinkTo to={`/user/${nameUser}`}>
+        <Typography variant="caption" sx={{ color: '#787c7e', marginLeft: 1, '&:hover': { textDecoration: 'underline' } }}>
+          u/
+          {nameUser}
+        </Typography>
+      </LinkTo>
+      {sharedFrom && (
+        <>
+          <CallSplitIcon sx={{ color: '#0079D3', marginLeft: '3px', transform: 'rotate(90deg)' }} fontSize="string" />
+          <Typography variant="caption" sx={{ color: '#787c7e', marginLeft: 1 }}>
+            cross posted by
+            {' '}
+            <LinkCross to={`/user/${sharedFrom?.author?.name}`}>
+              {sharedFrom?.author?.name}
+            </LinkCross>
+          </Typography>
+        </>
+      )}
+      <Typography variant="caption" sx={{ color: '#787c7e', marginLeft: 1 }}>
+        {' '}
+        {(moment.utc(Time).local().startOf('seconds')
+          .fromNow())}
+      </Typography>
+
+      {locked && <LockIcon sx={{ color: '#ffd635', marginLeft: '3px' }} fontSize="string" />}
+      {modState === 'spammed' && <Inventory2Icon sx={{ color: '#ff585b', marginLeft: '3px' }} fontSize="string" />}
+      {modState === 'approved' && <CheckCircleIcon sx={{ color: '#75d377', marginLeft: '3px' }} fontSize="string" />}
+      {modState === 'removed' && <DoDisturbAltIcon sx={{ color: '#ff585b', marginLeft: '3px' }} fontSize="string" />}
+
+    </HeaderPost>
+  );
+}
+
+export default PostHeader;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Posts_PostSide_PostSide.jsx.html b/docs/components_MainProfile_Profile_MainContent_Posts_PostSide_PostSide.jsx.html new file mode 100644 index 00000000..3985aedf --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Posts_PostSide_PostSide.jsx.html @@ -0,0 +1,109 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Posts/PostSide/PostSide.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Posts/PostSide/PostSide.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+import { postReactionsServer } from '../../../../profileServer';
+import {
+  UpArrow, DownArrow, SidebarQueueBox, UpArrowFilled, DownArrowFilled, Number,
+} from './styles';
+
+/**
+ * Sidebar of the post conatining arrow up and down
+ *
+ * @component PostSide
+ * @property {number} points -number of votes on a post
+ * @property {number} postVoteStatus -is the post upvoted or down voted or none
+ * @returns {React.Component} PostSide
+ */
+function PostSide(props) {
+  const {
+    postid, points, postVoteStatus, spam,
+  } = props;
+  const [postPoints, setPostPoints] = useState(points);
+  const [status, setStatus] = useState(postVoteStatus);
+
+  const handleClickUp = () => {
+    postReactionsServer(postid, 'vote', 1);
+    if (status === -1) setPostPoints(postPoints + 2);
+    else setPostPoints(postPoints + 1);
+    setStatus(1);
+  };
+  const handleClickDown = () => {
+    postReactionsServer(postid, 'vote', -1);
+    if (status === 1) setPostPoints(postPoints - 2);
+    else setPostPoints(postPoints - 1);
+    setStatus(-1);
+  };
+  const handleNoUpvote = () => {
+    postReactionsServer(postid, 'vote', 0);
+    setPostPoints(postPoints - 1);
+    setStatus(0);
+  };
+  const handleNoDownvote = () => {
+    postReactionsServer(postid, 'vote', 0);
+    setPostPoints(postPoints + 1);
+    setStatus(0);
+  };
+
+  return (
+    <SidebarQueueBox condition={spam?.toString()}>
+      {
+        (status === 1) ? <UpArrowFilled onClick={() => { handleNoUpvote(); }} /> : <UpArrow onClick={() => { handleClickUp(); }} />
+      }
+      <Number variant="caption" sx={{ fontWeight: 700 }}>{postPoints}</Number>
+      {
+        (status === -1) ? <DownArrowFilled onClick={() => { handleNoDownvote(); }} /> : <DownArrow onClick={() => { handleClickDown(); }} />
+      }
+    </SidebarQueueBox>
+  );
+}
+
+export default PostSide;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_ProfileMainContent.jsx.html b/docs/components_MainProfile_Profile_MainContent_ProfileMainContent.jsx.html new file mode 100644 index 00000000..48547fdc --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_ProfileMainContent.jsx.html @@ -0,0 +1,136 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/ProfileMainContent.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/ProfileMainContent.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import CommunitiesSubscriberProvider from '../../../../contexts/CommunitiesSubscriberContext';
+import CommunitiesProvider from '../../../../contexts/CommunitiesModeratorContext';
+import Content from './Content/Content';
+import FollowersList from './FollowersList/FollowersList';
+import HistoryTap from './HistoryTap/HistoryTap';
+import PostsFilteredTap from './PostsFilteredTap/PostsFilteredTap';
+import PostsTap from './PostsTap/PostsTap';
+import SavedTap from './SavedTap/SavedTap';
+import Sidebar from './Sidebar/Sidebar';
+import { ProfilePage } from './styles';
+import CommentsTap from '../../CommentsTap/CommentsTap';
+import UserProvider from '../../../../contexts/UserProvider';
+
+const renderSwitch = (param) => {
+  if (param === undefined || param === '?sort=new' || param === '?sort=hot' || param === '?sort=top' || param === '?sort=top&t=day') {
+    return (
+      <Content />
+    );
+  }
+
+  if (param === 'submitted' || param === 'submitted/?sort=new') {
+    return (
+      <PostsTap />
+    );
+  }
+  if (param === 'upvoted' || param === 'downvoted' || param === 'hidden') {
+    return (
+      <PostsFilteredTap />
+    );
+  }
+  if (param === 'saved') {
+    return (
+      <SavedTap />
+    );
+  }
+  if (param === 'history') {
+    return (
+      <HistoryTap />
+    );
+  }
+  if (param === 'comments') {
+    return (
+      <CommentsTap profile />
+    );
+  }
+  if (param === 'followers') {
+    return (
+      <FollowersList />
+    );
+  }
+  return (
+    <div />
+  );
+};
+
+/**
+ * MainContent if the profile page
+ *
+ * @component MainContentProfile
+ * @property  {function} handleClick to navigate to the subpage
+ * @return {React.Component} - MainContent
+ */
+
+function ProfileMainContent() {
+  const { subTitle, username } = useParams();
+  return (
+    <Box>
+      <UserProvider name={username}>
+        <CommunitiesProvider>
+          <CommunitiesSubscriberProvider>
+            <ProfilePage>
+              {renderSwitch(subTitle)}
+              <Sidebar />
+            </ProfilePage>
+          </CommunitiesSubscriberProvider>
+        </CommunitiesProvider>
+      </UserProvider>
+
+    </Box>
+  );
+}
+
+export default ProfileMainContent;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_SavedTap_SavedTap.jsx.html b/docs/components_MainProfile_Profile_MainContent_SavedTap_SavedTap.jsx.html new file mode 100644 index 00000000..30f5a98c --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_SavedTap_SavedTap.jsx.html @@ -0,0 +1,100 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/SavedTap/SavedTap.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/SavedTap/SavedTap.jsx

+ + + + + + +
+
+
import { useContext, useEffect, useState } from 'react';
+import { useParams } from 'react-router-dom';
+// import InfiniteScroll from 'react-infinite-scroll-component';
+import mergeTwo from '../../../../../utils/mergeSort';
+import renderText from '../../../../../utils/renderText';
+import { WideBox } from '../styles';
+import EmptyContent from '../../../EmptyContent/EmptyContent';
+import { UserContext } from '../../../../../contexts/UserProvider';
+import Post from '../Posts/Post';
+import SavedTapServer from './SavedTapServer';
+import Comments from '../../../Comments/Comments';
+// import { useListingContext } from '../../../../../contexts/ListingContext';
+
+/**
+ * Saved taps
+ *
+ * @component SavedTap
+ * @returns {React.Component} PostsFilteredTap
+ */
+function SavedTap() {
+  const { subTitle } = useParams();
+  const { username } = useContext(UserContext);
+  const [posts, comments] = SavedTapServer();
+  const [isContent, setIsContent] = useState(false);
+
+  // const { setPage } = useListingContext();
+  // const fetchMoreData = () => {
+  //   setPage((page) => page + 1);
+  // };
+
+  // check if the page have any content posts to show
+  useEffect(() => {
+    console.log(posts, comments);
+    setIsContent(false);
+    if (posts?.length > 0 || comments?.length > 0) { setIsContent(true); }
+  }, [username, posts, comments, subTitle]);
+
+  const emptyContent = renderText(subTitle);
+  return (
+    <WideBox>
+      {!isContent && <EmptyContent emptyContent={emptyContent} />}
+      {isContent && mergeTwo(posts, comments).map((entity, index) => (
+        entity.savedPost ? <Post key={`${index + 0}`} entity={entity.savedPost} type={subTitle} /> : <Comments key={`${index + 0}`} entity={entity.savedComment} />
+      ))}
+    </WideBox>
+  );
+}
+
+export default SavedTap;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Sidebar_Communities_Communities.jsx.html b/docs/components_MainProfile_Profile_MainContent_Sidebar_Communities_Communities.jsx.html new file mode 100644 index 00000000..daac3d3e --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Sidebar_Communities_Communities.jsx.html @@ -0,0 +1,80 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Sidebar/Communities/Communities.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Sidebar/Communities/Communities.jsx

+ + + + + + +
+
+
import { Typography } from '@mui/material';
+import { useContext } from 'react';
+
+import { CommunitiesContext } from '../../../../../../contexts/CommunitiesModeratorContext';
+import { InfoBox } from '../styles';
+import EntityComment from './EntityCommunity/EntityCommunity';
+
+/**
+ * all comunities you afre a moderator of
+ *
+ * @component Communities
+ * @returns {React.Component} Communities
+ */
+
+function Communities() {
+  // will fetch the comminities here
+  const { communities } = useContext(CommunitiesContext);
+
+  return (
+    <InfoBox>
+      <Typography variant="body2" sx={{ fontWeight: 700 }}>You&apos;re a moderator of these communities</Typography>
+      {communities?.map((community, index) => (
+        <EntityComment key={`${index + 0}`} community={community} />
+      ))}
+    </InfoBox>
+  );
+}
+
+export default Communities;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Sidebar_Sidebar.jsx.html b/docs/components_MainProfile_Profile_MainContent_Sidebar_Sidebar.jsx.html new file mode 100644 index 00000000..898aaa7f --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Sidebar_Sidebar.jsx.html @@ -0,0 +1,80 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Sidebar/Sidebar.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Sidebar/Sidebar.jsx

+ + + + + + +
+
+
import { useContext } from 'react';
+import { UserContext } from '../../../../../contexts/UserProvider';
+// import { useParams } from 'react-router';
+import BackHomeBottun from './BackHomeBottun/BackHome';
+import Communities from './Communities/Communities';
+import { SidebarBox } from './styles';
+import UserInfo from './UserInfo/UserInfo';
+
+/**
+ * sidebar in profile containing the userinfo and communities you are a moderator of
+ *
+ * @component Sidebar
+ * @returns {React.Component} Sidebar
+ */
+function Sidebar() {
+  // const { username } = useParams();
+  const { username } = useContext(UserContext);
+
+  return (
+    <SidebarBox>
+      <UserInfo username={username} />
+      <Communities />
+      <BackHomeBottun />
+    </SidebarBox>
+
+  );
+}
+
+export default Sidebar;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_Profile_MainContent_Sidebar_UserInfo_UserInfo.jsx.html b/docs/components_MainProfile_Profile_MainContent_Sidebar_UserInfo_UserInfo.jsx.html new file mode 100644 index 00000000..3136778b --- /dev/null +++ b/docs/components_MainProfile_Profile_MainContent_Sidebar_UserInfo_UserInfo.jsx.html @@ -0,0 +1,240 @@ + + + + + JSDoc: Source: components/MainProfile/Profile/MainContent/Sidebar/UserInfo/UserInfo.jsx + + + + + + + + + + +
+ +

Source: components/MainProfile/Profile/MainContent/Sidebar/UserInfo/UserInfo.jsx

+ + + + + + +
+
+
import { Box, CardMedia, Typography } from '@mui/material';
+import FilterVintageIcon from '@mui/icons-material/FilterVintage';
+import ArrowForwardIosOutlinedIcon from '@mui/icons-material/ArrowForwardIosOutlined';
+import PersonIcon from '@mui/icons-material/Person';
+import CakeIcon from '@mui/icons-material/Cake';
+import AddIcon from '@mui/icons-material/Add';
+import {
+  useEffect, useState,
+} from 'react';
+import moment from 'moment/moment';
+import { Link, useNavigate } from 'react-router-dom';
+import {
+  WideButton, EngineIcon, ProfilePic, ProfileBox,
+  UserInfoBox, UserName, InfoBox,
+  EntityBox, FollowersArrow, AddSocialLink, AddPost, MoreOptions, OptionsButtons, BootstrapDialog, LinkTo,
+} from './styles';
+// import { UserContext } from '../../../../../../contexts/UserProvider';
+import userInfoServer from './userInfoServer';
+import SocialLinks from '../../../../../SocialLinks/SocialLinks';
+import { PlatformIcon, Text } from '../../../../../SocialLinks/styles';
+/**
+ * UserInfo Box in sidebar containing all info of a user
+ *
+ * @component UserInfo
+ * @returns {React.Component} UserInfo
+ */
+function UserInfo({ username, createPost }) {
+  const [displayName, setDisplayName] = useState();
+  const [about, setAbout] = useState();
+  const [postKarma, setPostKarma] = useState();
+  const [commentKarma, setCommentKarma] = useState();
+  const [cake, setCake] = useState();
+  const [followers, setFollowers] = useState();
+  const [profilePic, setProfilePic] = useState();
+  const [coverPic, setCoverPic] = useState();
+  const [socialLinks, setSocialLinks] = useState([]);
+  const [open, setOpen] = useState(false);
+
+  const navigate = useNavigate();
+
+  const [info] = userInfoServer();
+  useEffect(() => {
+    setDisplayName(info?.displayName);
+    setAbout(info?.description);
+    setPostKarma(info?.postKarma);
+    setCommentKarma(info?.commentKarma);
+    setFollowers(info?.followersCount);
+    setCake(info?.createdAt);
+    setProfilePic(info?.profilePicture);
+    setCoverPic(info?.profileBackground);
+    setSocialLinks(info?.socialLinks);
+  }, [info]);
+
+  const [showList, setShowList] = useState(false);
+  const handleClickList = () => {
+    setShowList((prev) => !prev);
+  };
+
+  const handleClickOpen = () => {
+    setOpen(true);
+  };
+
+  const handleFollowes = () => {
+    navigate(`/user/${username}/followers`);
+  };
+
+  return (
+    <UserInfoBox>
+      <CardMedia
+        component="img"
+        height="94"
+        image={coverPic}
+        alt="cover image"
+        data-testid="cover-photo"
+      />
+
+      <ProfileBox>
+        <Box sx={{ display: 'flex' }}>
+          <Box>
+            <ProfilePic src={profilePic} alt="user photo" />
+
+          </Box>
+          <Link to="/settings">
+            <EngineIcon color="primary" />
+          </Link>
+        </Box>
+        <UserName variant="string">
+          {displayName}
+        </UserName>
+        <br />
+        <UserName variant="caption">
+          u/
+          {username}
+        </UserName>
+        <br />
+        <WideButton variant="contained" color="primary" endIcon={<ArrowForwardIosOutlinedIcon />}>
+          Create Avatar
+        </WideButton>
+        <UserName variant="body2">
+          {about}
+        </UserName>
+        <InfoBox>
+          <EntityBox>
+            <Typography variant="body2" sx={{ marginBottom: '5px' }}>Karma</Typography>
+            <Box sx={{ display: 'flex' }}>
+              <FilterVintageIcon fontSize="string" color="primary" sx={{ marginRight: '4px' }} />
+              <Typography variant="caption" sx={{ color: '#7c7c7c' }}>{postKarma + commentKarma }</Typography>
+            </Box>
+          </EntityBox>
+          <EntityBox>
+            <Typography variant="body2" sx={{ marginBottom: '5px' }}>Cake Day</Typography>
+            <Box sx={{ display: 'flex' }}>
+              <CakeIcon fontSize="string" color="primary" sx={{ marginRight: '4px' }} />
+              <Typography variant="caption" sx={{ color: '#7c7c7c' }}>
+                {moment(cake, 'YYYY-MM-DD-HH-mm').add(1, 'days').utc().format('MMMM DD, YYYY')}
+              </Typography>
+            </Box>
+          </EntityBox>
+          {followers > 0 && (
+          <EntityBox sx={{ cursor: 'pointer', maxWidth: 100 }} onClick={handleFollowes}>
+            <Typography variant="body2" sx={{ marginBottom: '5px' }}>Followers</Typography>
+            <Box sx={{ display: 'flex' }}>
+              <PersonIcon fontSize="string" color="primary" sx={{ marginRight: '4px' }} />
+              <Typography variant="caption" sx={{ color: '#7c7c7c' }}>{followers}</Typography>
+              <FollowersArrow fontSize="string" color="disabled" />
+            </Box>
+          </EntityBox>
+          )}
+        </InfoBox>
+
+        {/* social link part */}
+        <Box sx={{ display: 'flex', flexWrap: 'wrap' }}>
+          {socialLinks?.map((link, index) => (
+            <LinkTo href={`${link?.userLink}`} key={`${index + 0}`} target="_blank">
+              <Text key={`${index + 0}`}>
+                <PlatformIcon src={link?.social?.icon} />
+                {link?.displayText}
+              </Text>
+            </LinkTo>
+          ))}
+
+          {socialLinks?.length < 5
+            ? <AddSocialLink startIcon={<AddIcon />} variant="contained" onClick={handleClickOpen}>Add social link</AddSocialLink>
+            : <AddSocialLink variant="contained" sx={{ minWidth: '50px', padding: 0 }} onClick={() => { window.location.pathname = 'settings/profile'; }}>Edit</AddSocialLink>}
+        </Box>
+        {/* social link part */}
+
+        {!createPost && <AddPost variant="contained" onClick={() => { navigate('/submit'); }}>Add Post</AddPost>}
+
+        {/* popup component to add social link */}
+        <BootstrapDialog
+          onClose={(event, reason) => {
+            console.log('out');
+            if (reason !== 'backdropClick' && reason !== 'escapeKeyDown') {
+              setOpen(false);
+              console.log('to');
+            }
+          }}
+          aria-labelledby="customized-dialog-title"
+          open={open}
+          keepMounted
+        >
+          <SocialLinks onClose={(event, reason) => {
+            console.log('out');
+            if (reason !== 'backdropClick' && reason !== 'escapeKeyDown') {
+              setOpen(false);
+
+              console.log('bo');
+            }
+          }}
+          />
+        </BootstrapDialog>
+        {/* popup component to add social link */}
+
+        {showList
+          ? (
+            <>
+              <OptionsButtons data-testid="option">Profile moderation</OptionsButtons>
+              <OptionsButtons>Add to Custom Feed</OptionsButtons>
+              <MoreOptions onClick={() => { handleClickList(); }}>Fewer options</MoreOptions>
+            </>
+          ) : <MoreOptions data-testid="show-more" onClick={() => { handleClickList(); }}>More options</MoreOptions>}
+      </ProfileBox>
+
+    </UserInfoBox>
+  );
+}
+
+export default UserInfo;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_MainProfile_mainProfileServer.js.html b/docs/components_MainProfile_mainProfileServer.js.html new file mode 100644 index 00000000..af7f2473 --- /dev/null +++ b/docs/components_MainProfile_mainProfileServer.js.html @@ -0,0 +1,104 @@ + + + + + JSDoc: Source: components/MainProfile/mainProfileServer.js + + + + + + + + + + +
+ +

Source: components/MainProfile/mainProfileServer.js

+ + + + + + +
+
+
import { useEffect, useRef, useState } from 'react';
+import axios from '../../services/instance';
+
+import useFetch from '../../hooks/useFetch';
+
+const UserInfoServer = (username) => {
+  const [data, dataError, statusCode] = useFetch(`users/${username}/about`);
+
+  useEffect(() => {
+    if (statusCode === 401) {
+      window.location.pathname = 'login';
+    }
+  }, [data, dataError, statusCode]);
+  return [data?.user, statusCode];
+};
+
+export default UserInfoServer;
+
+/**
+ * follow a user
+ *
+ * @property {string} username - username of user to be followed
+ * @returns {object} provided response through backend
+ */
+
+export const followRequest = (username, isFollowed, handleNotBlocked) => {
+  const [data, setData] = useState(null);
+
+  const isFirstRun = useRef(true);
+  useEffect(() => {
+    if (isFollowed === undefined) {
+      return;
+    }
+    if (isFirstRun.current) {
+      isFirstRun.current = false;
+      return;
+    }
+    axios.post(`/users/${username}/${isFollowed ? 'follow' : 'unfollow'}`, {
+
+    }).then((response) => {
+      // console.log(response);
+      if (response.status === 200 || response.status === 201) {
+        handleNotBlocked();
+      } else if (response.status === 401) {
+        window.location.pathname = 'login';
+      }
+      setData(response.data);
+    }).catch((error) => {
+      console.log(error);
+    });
+  }, [username, isFollowed]);
+  return [data];
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Messages_MessageForm_messageFormServer.js.html b/docs/components_Messages_MessageForm_messageFormServer.js.html new file mode 100644 index 00000000..c562e186 --- /dev/null +++ b/docs/components_Messages_MessageForm_messageFormServer.js.html @@ -0,0 +1,72 @@ + + + + + JSDoc: Source: components/Messages/MessageForm/messageFormServer.js + + + + + + + + + + +
+ +

Source: components/Messages/MessageForm/messageFormServer.js

+ + + + + + +
+
+
import axios from '../../../services/instance';
+import { redirectLogin } from '../../../utils/Redirect';
+/**
+ * - Notifications Fetch
+ */
+
+export const postData = async (data) => {
+  const api = '/messages';
+  const message = '';
+  const flag = 'error';
+  await axios.post(`${api}`, data)
+    .then((response) => {
+      console.log(response);
+    }).catch((error) => {
+      console.log(error);
+      if (error?.response?.status === 401) {
+        redirectLogin();
+      }
+    });
+  return [message, flag];
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Messages_MessageSent_messageSentServer.js.html b/docs/components_Messages_MessageSent_messageSentServer.js.html new file mode 100644 index 00000000..1c7a5652 --- /dev/null +++ b/docs/components_Messages_MessageSent_messageSentServer.js.html @@ -0,0 +1,67 @@ + + + + + JSDoc: Source: components/Messages/MessageSent/messageSentServer.js + + + + + + + + + + +
+ +

Source: components/Messages/MessageSent/messageSentServer.js

+ + + + + + +
+
+
import { useEffect } from 'react';
+import useFetch from '../../../hooks/useFetch';
+import { redirectLogin } from '../../../utils/Redirect';
+/**
+ * - Messages Fetch
+ */
+export const messageSentFetch = () => {
+  const api = '/messages/sent';
+  const [data, statusCode, message] = useFetch(api);
+  useEffect(() => {
+    if (statusCode === 401) {
+      redirectLogin();
+    }
+  }, [data, message]);
+  return [data];
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Messages_MessagesAll_messageAllServer.js.html b/docs/components_Messages_MessagesAll_messageAllServer.js.html new file mode 100644 index 00000000..562a0508 --- /dev/null +++ b/docs/components_Messages_MessagesAll_messageAllServer.js.html @@ -0,0 +1,79 @@ + + + + + JSDoc: Source: components/Messages/MessagesAll/messageAllServer.js + + + + + + + + + + +
+ +

Source: components/Messages/MessagesAll/messageAllServer.js

+ + + + + + +
+
+
import { useEffect, useState } from 'react';
+import axios from '../../../services/instance';
+import { redirectLogin } from '../../../utils/Redirect';
+/**
+ * - Notifications Fetch
+ */
+
+export const messagesAllServer = () => {
+  const api = '/messages/all';
+  const [data, setData] = useState([]);
+  const [message, setMessage] = useState([]);
+  useEffect(() => {
+    axios.get(api)
+      .then((actualData) => {
+        const output = [];
+
+        setData(actualData.data.data);
+        setMessage(output);
+        console.log(actualData.data);
+      }).catch((error) => {
+        console.log(error);
+        if (error?.response?.status === 401) {
+          redirectLogin();
+        }
+      });
+  }, [api]);
+  return [data, message];
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Messages_MessagesDrive_MessagesDriveServer.js.html b/docs/components_Messages_MessagesDrive_MessagesDriveServer.js.html new file mode 100644 index 00000000..bcfd3254 --- /dev/null +++ b/docs/components_Messages_MessagesDrive_MessagesDriveServer.js.html @@ -0,0 +1,105 @@ + + + + + JSDoc: Source: components/Messages/MessagesDrive/MessagesDriveServer.js + + + + + + + + + + +
+ +

Source: components/Messages/MessagesDrive/MessagesDriveServer.js

+ + + + + + +
+
+
import { useEffect, useState } from 'react';
+import axios from '../../../services/instance';
+import { redirectLogin } from '../../../utils/Redirect';
+/**
+ * - Notifications Fetch
+ */
+
+export const messagesServer = () => {
+  const api = '/messages';
+  const [data, setData] = useState([]);
+  const [message, setMessage] = useState([]);
+  useEffect(() => {
+    axios.get(api)
+      .then((actualData) => {
+        // const All = actualData.data.data.filter((e) => e.type !== 'userMessage');
+        const output = [];
+        // const userMessage = actualData.data.data.filter((e) => e.type === 'userMessage');
+        // const ids = [...new Set(userMessage.map((i) => i?.subject?._id))];
+        // ids.forEach((id) => {
+        //   const res = userMessage.filter((name) => name?.subject?._id === id);
+        //   output.push(res);
+        // });
+        // console.log(output);
+        // console.log(All);
+        setData(actualData.data.data);
+        setMessage(output);
+        console.log(actualData.data);
+      }).catch((error) => {
+        console.log(error);
+        if (error?.response?.status === 401) {
+          redirectLogin();
+        }
+      });
+  }, [api]);
+  return [data, message];
+};
+
+export const AcceptServer = (subredditName) => {
+  const api = `/subreddits/${subredditName}/accept/invitation`;
+
+  axios.post(api)
+    .then((actualData) => {
+      // const All = actualData.data.data.filter((e) => e.type !== 'userMessage');
+
+      // setData(actualData.data.data);
+
+      console.log(actualData.data);
+    }).catch((error) => {
+      console.log(error);
+      if (error?.response?.status === 401) {
+        redirectLogin();
+      }
+    });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Messages_MessagesUnread_messageUnreadServer.js.html b/docs/components_Messages_MessagesUnread_messageUnreadServer.js.html new file mode 100644 index 00000000..eb4ebc03 --- /dev/null +++ b/docs/components_Messages_MessagesUnread_messageUnreadServer.js.html @@ -0,0 +1,93 @@ + + + + + JSDoc: Source: components/Messages/MessagesUnread/messageUnreadServer.js + + + + + + + + + + +
+ +

Source: components/Messages/MessagesUnread/messageUnreadServer.js

+ + + + + + +
+
+
import { useEffect, useState } from 'react';
+import axios from '../../../services/instance';
+import { redirectLogin } from '../../../utils/Redirect';
+/**
+ * - Notifications Fetch
+ */
+
+export const messagesAllServer = () => {
+  const api = '/messages/unread';
+
+  const [data, setData] = useState([]);
+  const [message, setMessage] = useState([]);
+  useEffect(() => {
+    axios.get(api)
+      .then((actualData) => {
+        const output = [];
+        setData(actualData.data.data);
+        setMessage(output);
+        console.log(actualData.data);
+      }).catch((error) => {
+        console.log(error);
+        if (error?.response?.status === 401) {
+          redirectLogin();
+        }
+      });
+  }, [api]);
+
+  return [data, message];
+};
+export const markAllRead = () => {
+  const markAsRead = '/messages/mark_as_read';
+
+  axios.patch(markAsRead)
+    .then((actualData) => {
+      console.log(actualData.data);
+    }).catch((error) => {
+      console.log(error);
+      if (error?.response?.status === 401) {
+        redirectLogin();
+      }
+    });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Messages_PostRepliesServer.js.html b/docs/components_Messages_PostRepliesServer.js.html new file mode 100644 index 00000000..ea9d6b10 --- /dev/null +++ b/docs/components_Messages_PostRepliesServer.js.html @@ -0,0 +1,106 @@ + + + + + JSDoc: Source: components/Messages/PostRepliesServer.js + + + + + + + + + + +
+ +

Source: components/Messages/PostRepliesServer.js

+ + + + + + +
+
+
import { useEffect, useState } from 'react';
+import axios from '../../services/instance';
+import { redirectLogin } from '../../utils/Redirect';
+/**
+ * - Notifications Fetch
+ */
+
+export const repliesServer = () => {
+  const api = '/messages/post_replies';
+  const [data, setData] = useState([]);
+  useEffect(() => {
+    axios.get(api)
+      .then((actualData) => {
+        setData(actualData.data);
+        console.log(actualData.data);
+      }).catch((error) => {
+        console.log(error);
+
+        if (error?.response?.status === 401) {
+          redirectLogin();
+        }
+      });
+  }, [api]);
+  return [data];
+};
+
+export const deleteMessage = (id) => {
+  console.log('sa');
+  const api = `/messages/${id}`;
+
+  axios.delete(api)
+    .then((actualData) => {
+      console.log(actualData.data);
+    }).catch((error) => {
+      console.log(error);
+
+      if (error?.response?.status === 401) {
+        redirectLogin();
+      }
+    });
+};
+export const replayMessage = (id, text) => {
+  console.log('sa');
+  const api = `/messages/${id}/reply`;
+  axios.post(api, { text })
+    .then((actualData) => {
+      console.log(actualData.data);
+    }).catch((error) => {
+      console.log(error);
+
+      if (error?.response?.status === 401) {
+        redirectLogin();
+      }
+    });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Messages_messageSever.js.html b/docs/components_Messages_messageSever.js.html new file mode 100644 index 00000000..05cf868c --- /dev/null +++ b/docs/components_Messages_messageSever.js.html @@ -0,0 +1,82 @@ + + + + + JSDoc: Source: components/Messages/messageSever.js + + + + + + + + + + +
+ +

Source: components/Messages/messageSever.js

+ + + + + + +
+
+
import axios from '../../services/instance';
+import { redirectLogin } from '../../utils/Redirect';
+/**
+ * - Notifications Fetch
+ */
+
+export const blockuser = async (user) => {
+  const api = `/users/${user}/block_user`;
+  let message = '';
+  let flag = 'error';
+  await axios.post(`${api}`)
+    .then((response) => {
+      console.log(response);
+      flag = 'success';
+      message = 'operation done successfully';
+    }).catch((error) => {
+      console.log(error);
+      if (error?.response?.status === 401) {
+        redirectLogin();
+      } else if (error?.response?.status === 400) {
+        message = 'try blocking yourself';
+      } else if (error?.response?.status === 404) {
+        message = 'user not found';
+      } else if (error?.response?.status === 405) {
+        message = 'other user has blocked you';
+      } else {
+        message = 'already blocked';
+      }
+    });
+  return [message, flag];
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Community_CommumityMainTopics_CmmunityMainTopics.jsx.html b/docs/components_Moderation_Community_CommumityMainTopics_CmmunityMainTopics.jsx.html new file mode 100644 index 00000000..023b2933 --- /dev/null +++ b/docs/components_Moderation_Community_CommumityMainTopics_CmmunityMainTopics.jsx.html @@ -0,0 +1,157 @@ + + + + + JSDoc: Source: components/Moderation/Community/CommumityMainTopics/CmmunityMainTopics.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/Community/CommumityMainTopics/CmmunityMainTopics.jsx

+ + + + + + +
+
+
import {
+  ListItem, ListItemText, ClickAwayListener,
+} from '@mui/material';
+import { useEffect, useState } from 'react';
+import ExpandMoreOutlinedIcon from '@mui/icons-material/ExpandMoreOutlined';
+import ExpandLessOutlinedIcon from '@mui/icons-material/ExpandLessOutlined';
+// import patchData from './ModerationServer';
+import {
+  Select, Lists, SelectContainer,
+} from './style';
+import AddList from './CommunityTopics/CommunityTopics';
+/**
+* List of Primary topics in community
+* @component
+ * @property  {function} changeShow show list of topics or not
+ * @property  {function} ListSelected to set the primary topic
+ * @property  {function} handleClickAway handel on select item
+ *
+ * @return {React.Component} - Moderators section in sidebar
+ */
+function CommunityMianTopic(props) {
+  const {
+    topics, Name, primaryTopic, setTopics, setPrimaryTopic,
+  } = props;
+  const [more, setMore] = useState(false);
+  const [listOfTopics, setListOfTopics] = useState(false);
+  const [selection, setSelection] = useState(primaryTopic);
+
+  const primary = ['Activism', 'Art', 'Addiction Support', 'Anime', 'Beauty and Makeup', 'Business, Economics, and Finance', 'Careers', 'Cars and Motor Vehicles',
+    'Celebrity', 'Crafts and DIY', 'Crypto', 'Culture, Race, and Ethnicity', 'Ethics and Philosophy', 'Family and Relationships', 'Fashion', 'Fitness and Nutrition',
+    'Food and Drink', 'Funny/Humor', 'Gamming', 'Gender', 'History', 'Hobbies', 'Home and Garden', 'Home and Garden', 'Learning and Education', 'Law', 'Marketplace and Deals',
+    'Mature Themes and Adult Content', 'Medical and Mental Health', "Men's Health", 'Meta/Reddit', 'Outdoors and Nature', 'Militery', 'Moves', 'Music', 'Outdoors and Nature', 'Place',
+    'Podcasts and Streamers', 'Polices', 'Progeamming', 'Reading, Writing, and Literature'];
+
+  useEffect(() => {
+    setSelection(primaryTopic);
+    if (primaryTopic === 'Add a Primary Topic' || selection === 'Add a Primary Topic') {
+      setListOfTopics(false);
+    } else {
+      setListOfTopics(true);
+    }
+  }, [primaryTopic]);
+  // show select list or not
+  const changeShow = () => {
+    setMore(!more);
+    // setSelection('Add a Primary Topic');
+  };
+
+  // handel on select item
+  const ListSelected = (e) => {
+    setMore(!more);
+    setSelection(e.target.textContent);
+    setListOfTopics(true);
+    setPrimaryTopic(e.target.textContent);
+  };
+
+  // close the list in  click away
+  const handleClickAway = () => {
+    setMore(false);
+  };
+  return (
+    <>
+      <SelectContainer
+        onClick={changeShow}
+      >
+        <Select data-testid="select">{selection}</Select>
+        {!more && <ExpandMoreOutlinedIcon color="primary" sx={{ marginTop: '7px', marginLeft: '5px' }} />}
+        {more && <ExpandLessOutlinedIcon color="primary" sx={{ marginTop: '7px', marginLeft: '5px' }} />}
+      </SelectContainer>
+
+      {more
+      && (
+        <ClickAwayListener onClickAway={handleClickAway}>
+          <Lists
+            data-testid="list"
+            subheader={<li />}
+          >
+            {[0].map((sectionId) => (
+              <li key={`section-${sectionId}`}>
+                <ul>
+                  {primary.map((item) => (
+                    <ListItem key={`item-${sectionId}-${item}`}>
+                      <ListItemText
+                        primary={`${item}`}
+                        sx={{
+                          span: {
+                            fontWeight: 700,
+                            fontSize: 13,
+                            cursor: 'pointer',
+                          },
+                        }}
+                        onClick={ListSelected}
+                      />
+                    </ListItem>
+                  ))}
+                </ul>
+              </li>
+            ))}
+          </Lists>
+        </ClickAwayListener>
+      )}
+      {listOfTopics && <AddList topics={topics} Name={Name} listOfTopics={listOfTopics} setTopics={setTopics} />}
+    </>
+  );
+}
+export default CommunityMianTopic;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Community_CommumityMainTopics_CommunityTopics_AddTopic_AddTopic.jsx.html b/docs/components_Moderation_Community_CommumityMainTopics_CommunityTopics_AddTopic_AddTopic.jsx.html new file mode 100644 index 00000000..55418125 --- /dev/null +++ b/docs/components_Moderation_Community_CommumityMainTopics_CommunityTopics_AddTopic_AddTopic.jsx.html @@ -0,0 +1,110 @@ + + + + + JSDoc: Source: components/Moderation/Community/CommumityMainTopics/CommunityTopics/AddTopic/AddTopic.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/Community/CommumityMainTopics/CommunityTopics/AddTopic/AddTopic.jsx

+ + + + + + +
+
+
import ClearOutlinedIcon from '@mui/icons-material/ClearOutlined';
+import { Box } from '@mui/material';
+import {
+  Add, Input, Text,
+} from './style';
+
+/**
+   * AddButton(community topics)
+   * @component
+   * @property  {function} removeItem remove ele from list of topics
+   * @property  {function} handleChange remove ele from list of topics
+   * @property  {function} trueShawList shoe list of topics
+   * @property  {function} handleKeyDown add ele to list of topics
+
+   * @param {string} tempString - list of topics
+   * @return {React.Component} - AddButton(community topics)
+   */
+
+function AddBtn(props) {
+  const {
+    tempString, removeItem, handleChange, handleKeyDown, trueShawList,
+  } = props;
+  return (
+
+    <Add data-testid="add" id="add">
+      <>
+        <Box sx={{
+          display: 'flex', flexDirection: 'row', flexWrap: 'wrap', width: '100%',
+        }}
+        >
+          {tempString?.length > 0 && tempString?.map((tag, index) => (
+            <Text key={`${index + 0}`}>
+              {tag}
+              <ClearOutlinedIcon
+                fontSize="small"
+                onClick={() => {
+                  removeItem(index);
+                }}
+              />
+            </Text>
+          )) }
+        </Box>
+        <Input
+          data-testid="input"
+          id="input"
+          type="text"
+          onChange={handleChange}
+          onFocus={trueShawList}
+          onInput={(e) => {
+            // eslint-disable-next-line radix
+            e.target.style.height = `${e.target.scrollHeight}px`;
+          }}
+          onKeyDown={handleKeyDown}
+        />
+      </>
+    </Add>
+  );
+}
+export default AddBtn;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Community_CommumityMainTopics_CommunityTopics_CommunityTopics.jsx.html b/docs/components_Moderation_Community_CommumityMainTopics_CommunityTopics_CommunityTopics.jsx.html new file mode 100644 index 00000000..b94a3c07 --- /dev/null +++ b/docs/components_Moderation_Community_CommumityMainTopics_CommunityTopics_CommunityTopics.jsx.html @@ -0,0 +1,183 @@ + + + + + JSDoc: Source: components/Moderation/Community/CommumityMainTopics/CommunityTopics/CommunityTopics.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/Community/CommumityMainTopics/CommunityTopics/CommunityTopics.jsx

+ + + + + + +
+
+
import {
+  ClickAwayListener,
+  //  Box, ClickAwayListener,
+  ListItem, ListItemText,
+} from '@mui/material';
+import { useState, useEffect } from 'react';
+
+// import patchData from '../ModerationServer';
+
+import AddBtn from './AddTopic/AddTopic';
+import {
+  AboutContent,
+  Lists,
+} from './style';
+
+const primary = ['Activism', 'Art', 'Addiction Support', 'Anime', 'Beauty and Makeup', 'Business, Economics, and Finance', 'Careers', 'Cars and Motor Vehicles',
+  'Celebrity', 'Crafts and DIY', 'Crypto', 'Culture, Race, and Ethnicity', 'Ethics and Philosophy', 'Family and Relationships', 'Fashion', 'Fitness and Nutrition',
+  'Food and Drink', 'Funny/Humor', 'Gamming', 'Gender', 'History', 'Hobbies', 'Home and Garden', 'Home and Garden', 'Learning and Education', 'Law', 'Marketplace and Deals',
+  'Mature Themes and Adult Content', 'Medical and Mental Health', "Men's Health", 'Meta/Reddit', 'Outdoors and Nature', 'Militery', 'Moves', 'Music', 'Outdoors and Nature', 'Place',
+  'Podcasts and Streamers', 'Polices', 'Progeamming', 'Reading, Writing, and Literature'];
+  /**
+   * AddList(community topics)
+   * @component
+   * @property  {function} handleKeyDown handel on press enter to add the community topic
+   * @property  {function} removeItem to remove element from list of topics
+   * @property  {function} ListSelected add item when select from list
+   * @property  {function} trueShawList show list
+   * @property  {function} handleClickAway close list a
+   * @return {React.Component} - AddList(community topics)
+   */
+function AddList(props) {
+  const {
+    topics, setTopics,
+  } = props;
+  const [showList, setShowList] = useState(false);
+  // eslint-disable-next-line prefer-const
+  const [tags, setTags] = useState(topics);
+  const [tempString, setTempString] = useState(tags);
+  const [count, setCount] = useState(tags?.length);
+
+  useEffect(() => {
+    setTags(topics);
+    setTempString(topics);
+  }, [topics]);
+  // save the change in input field to get count if char
+  const handleChange = (event) => {
+    console.log((event.target > 'Text').length);
+    if (event.target.value.length < 26) {
+      setCount((event.target > 'Text').length);
+    }
+  };
+    // handel on press enter to add the community topic
+  const handleKeyDown = (e) => {
+    if ((tempString.length < 25 && !tempString.includes(e.target.value))) {
+      if (e.key !== 'Enter') return;
+      const { value } = e.target;
+      if (!value.trim()) return;
+      setTempString([...tempString, value]);
+    }
+    e.target.value = '';
+  };
+    // to rempve element when press x
+  const removeItem = (value) => {
+    setTempString(tempString.filter((ele, index) => index !== value));
+  };
+
+  // add item when select from list
+  const ListSelected = (e) => {
+    e.stopPropagation();
+    if (!tempString.includes(e.target.textContent)) {
+      setTempString([...tempString, e.target.textContent]);
+      const btn = document.getElementById('add');
+      btn.click();
+      const input = document.getElementById('input');
+      input.focus();
+    }
+  };
+  const trueShawList = () => {
+    setShowList(true);
+  };
+  const handleClickAway = () => {
+    setShowList(false);
+    setTopics(tempString);
+  };
+  return (
+    <ClickAwayListener onClickAway={handleClickAway}>
+
+      <AboutContent>
+        <AddBtn
+          trueShawList={trueShawList}
+          handleChange={handleChange}
+          handleKeyDown={handleKeyDown}
+          removeItem={removeItem}
+          tempString={tempString}
+          count={count}
+        />
+        {
+            tempString?.length < 25 && showList
+            && (
+              <Lists
+                subheader={<li />}
+              >
+                {[0].map((sectionId) => (
+                  <li key={`section-${sectionId}`}>
+                    <ul>
+                      {primary.map((item) => (
+                        <ListItem key={`item-${sectionId}-${item}`}>
+                          <ListItemText
+                            primary={`${item}`}
+                            sx={{
+                              span: {
+                                fontWeight: 700,
+                                fontSize: 13,
+                                cursor: 'pointer',
+                              },
+                            }}
+                            onClick={ListSelected}
+                          />
+                        </ListItem>
+                      ))}
+                    </ul>
+                  </li>
+                ))}
+              </Lists>
+            )
+          }
+      </AboutContent>
+    </ClickAwayListener>
+
+  );
+}
+export default AddList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Community_Community.jsx.html b/docs/components_Moderation_Community_Community.jsx.html new file mode 100644 index 00000000..570d8419 --- /dev/null +++ b/docs/components_Moderation_Community_Community.jsx.html @@ -0,0 +1,297 @@ + + + + + JSDoc: Source: components/Moderation/Community/Community.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/Community/Community.jsx

+ + + + + + +
+
+
/* eslint-disable max-len */
+import { Box, Switch, Typography } from '@mui/material';
+import { useEffect, useMemo, useState } from 'react';
+import { useParams } from 'react-router-dom';
+import patchData from '../../SubReddit/SideBar/Mderation/ModerationServer';
+import FormDialog from '../../HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/PopUp';
+import getSubredditAllData from '../../SubReddit/SubrridetDataServer';
+import CommunityMianTopic from './CommumityMainTopics/CmmunityMainTopics';
+import RadioBtn from './CommunityType/CommunityType';
+import CountrySelect from './Region/Region';
+import {
+  AboutString, AboutSubString, Add, AddFlair, Adult, BackHomeButton, Container, Count, Disc, FlexBox, FlexBoxColumn, InputName, LeftAlighne,
+  NotFoundBox, NotFountImage, NSFWs, Section, SmallDisc, TextArea, TotalContainer, Warning,
+} from './style';
+import Done from '../../AlertMessage';
+
+/**
+ * Community
+ * @component
+ * @property  {function} myType to set the type of the community
+ * @property  {function} check to check if the community name length less than 100
+ * @property  {function} checkDisc to check if the community description length less than 100
+ * @property  {function} redirect to redirect to homepage
+ * @property  {function} createCommunity to show community form
+ * @property  {function} SendData to send new subreddit data to backend
+
+* @param {string} t - the new type of the community
+* @param {string} e - the input feild which is clicked
+* @return {React.Component} - Community
+ */
+
+export default function Community() {
+  const [count, setCount] = useState(100);
+  const [countDisc, setCountDisc] = useState(100);
+
+  const [type, setType] = useState('');
+  const [primaryTopic, setPrimaryTopic] = useState('');
+  const [disc, setDisc] = useState('');
+  const [name, setName] = useState('');
+  const [Location, setRegion] = useState('');
+  const [nsfw, setNsfw] = useState();
+  const [topics, setTopics] = useState([]);
+  const [showPopUp, setShowPopUp] = useState(false);
+
+  const [exist, setExist] = useState(true);
+
+  const { subReddit } = useParams();
+
+  const [data, dataError, statusCode] = getSubredditAllData(subReddit);
+  const value = useMemo(() => ({ data, dataError }), [data, dataError]);
+  console.log(value, data);
+  useEffect(() => {
+    if (statusCode === 404) {
+      setExist(false);
+    }
+    setName(data?.name);
+    setDisc(data?.description);
+    setTopics(data?.topics);
+    setPrimaryTopic(data?.primaryTopic);
+    setType(data?.type);
+    setNsfw(data?.nsfw);
+    setRegion(data?.region);
+  }, [data, statusCode]);
+
+  useEffect(() => {
+    // console.log(disc.length);
+    const x = disc?.length;
+    const y = subReddit?.length;
+    setCount(100 - y);
+    setCountDisc(100 - x);
+  }, [disc, subReddit]);
+
+  useEffect(() => {
+    console.log(type);
+    console.log(nsfw === true);
+    console.log(Location);
+  }, [nsfw]);
+  const myType = (t) => {
+    setType(t);
+  };
+  const check = (e) => {
+    const ele = e?.target?.value;
+    setName(ele);
+    setCount(100 - ele.length);
+  };
+  const checkDisc = (e) => {
+    const ele = e?.target?.value;
+    setDisc(ele);
+    setCountDisc(100 - ele.length);
+  };
+  const redirect = () => {
+    window.location.pathname = '/';
+  };
+
+  const createCommunity = async () => {
+    await setShowPopUp(true);
+    const ele = document.getElementById('popup-form-button');
+    ele.click();
+  };
+  const SendData = () => {
+    const region = document.getElementById('country-select-demo').value;
+    patchData(subReddit, {
+      topics,
+      primaryTopic,
+      name,
+      description: disc,
+      nsfw,
+      region,
+      type,
+    }); // fetch api
+    Done('Chnges Saved');
+  };
+  return (
+
+    exist
+      ? (
+        <TotalContainer>
+          <AddFlair><Add onClick={SendData}>Save Change</Add></AddFlair>
+          <LeftAlighne>
+            <Container>
+              <AboutString>
+                Community settings
+              </AboutString>
+              <Disc>COMMUNITY PROFILE</Disc>
+              <Section>
+                <AboutSubString>
+                  Community name
+                </AboutSubString>
+                <InputName
+                  type="text"
+                  defaultValue={subReddit}
+                  onChange={check}
+                  onInput={(e) => {
+                  // eslint-disable-next-line radix
+                    e.target.value = e.target.value.slice(0, 100);
+                  }}
+                />
+                <Count
+                  condition={(count === 0).toString()}
+                >
+                  {count}
+                  {' '}
+                  Characters remaining
+                </Count>
+              </Section>
+              {/* community topics */}
+              <Section>
+                <FlexBox>
+                  <FlexBoxColumn>
+                    <AboutSubString>Community topics</AboutSubString>
+                    <SmallDisc>This will help Reddit recommend your community to relevant users and other discovery experiences.</SmallDisc>
+                  </FlexBoxColumn>
+                  <Count
+                    condition={(count === 25).toString()}
+                  >
+                    {topics?.length}
+                    /
+                    25
+                  </Count>
+                </FlexBox>
+                <CommunityMianTopic topics={topics} Name={name} primaryTopic={primaryTopic} setTopics={setTopics} setPrimaryTopic={setPrimaryTopic} />
+              </Section>
+              <Section>
+                <AboutSubString>
+                  Community description
+                </AboutSubString>
+                <SmallDisc>
+                  This is how new members come to understand your community.
+                </SmallDisc>
+                <TextArea
+                  onChange={checkDisc}
+                  defaultValue={disc}
+                  onInput={(e) => {
+                  // eslint-disable-next-line radix
+                    e.target.value = e.target.value.slice(0, 100);
+                  }}
+                />
+                <Count
+                  condition={(countDisc === 0).toString()}
+                >
+                  {countDisc}
+                  {' '}
+                  Characters remaining
+                </Count>
+              </Section>
+              <Section>
+                <Disc>COMMUNITY LOCATION AND MAIN LANGUAGE</Disc>
+                <SmallDisc marginTop="-14px">
+                  Adding a location helps your community show up in search results and
+                  recommendations and helps local redditors find it easier.
+                </SmallDisc>
+              </Section>
+              <Section>
+                <AboutSubString>
+                  Region
+                </AboutSubString>
+                <Box sx={{ marginLeft: '17px' }}>
+                  <CountrySelect Location={Location?.toString()} />
+                </Box>
+              </Section>
+              <Section>
+                <Disc>COMMUNITY TYPE</Disc>
+              </Section>
+              <Section>
+                {(type === 'Public')
+                && <RadioBtn myType={myType} type="Public" />}
+                {(type === 'Restricted')
+                && <RadioBtn myType={myType} type="Restricted" />}
+                { (type === 'Private')
+               && <RadioBtn myType={myType} type="Private" />}
+              </Section>
+              <Section>
+                <FlexBox>
+                  <FlexBoxColumn>
+                    <Adult>
+                      <Warning>18+ year old community</Warning>
+                      <NSFWs>NSFW</NSFWs>
+                    </Adult>
+                    <SmallDisc>
+                      When your community is marked as an 18+ community, users must be flagged as 18+ in their user settings
+                    </SmallDisc>
+                  </FlexBoxColumn>
+                  { nsfw
+                    && <Switch defaultChecked onClick={() => { setNsfw(!nsfw); }} />}
+                  {!nsfw
+                    && <Switch defaultChecked={false} onClick={() => { setNsfw(!nsfw); }} />}
+                </FlexBox>
+              </Section>
+            </Container>
+          </LeftAlighne>
+        </TotalContainer>
+      )
+      : (
+        <NotFoundBox>
+          <NotFountImage src="https://www.redditstatic.com/desktop2x/img/snoomoji/snoo_thoughtful.png" />
+          <Typography sx={{ fontWeight: 700, marginBottom: 2, fontSize: '18px' }}>Sorry, there arenโ€™t any communities on Reddit with that name.</Typography>
+          <Typography sx={{ marginBottom: 4, fontSize: '14px' }}>This community may have been banned or the community name is incorrect.</Typography>
+          <Box>
+            <BackHomeButton variant="outlined" onClick={createCommunity} sx={{ textTransform: 'unset' }}>Create community</BackHomeButton>
+            <BackHomeButton variant="contained" onClick={redirect}>Go Home</BackHomeButton>
+          </Box>
+          {showPopUp && <Box sx={{ display: 'absolute' }}><FormDialog display="none" /></Box>}
+        </NotFoundBox>
+      )
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Community_CommunityType_CommunityType.jsx.html b/docs/components_Moderation_Community_CommunityType_CommunityType.jsx.html new file mode 100644 index 00000000..b56019d0 --- /dev/null +++ b/docs/components_Moderation_Community_CommunityType_CommunityType.jsx.html @@ -0,0 +1,112 @@ + + + + + JSDoc: Source: components/Moderation/Community/CommunityType/CommunityType.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/Community/CommunityType/CommunityType.jsx

+ + + + + + +
+
+
import {
+  FormControl, FormControlLabel, Radio, RadioGroup,
+} from '@mui/material';
+import PersonIcon from '@mui/icons-material/Person';
+import VisibilityIcon from '@mui/icons-material/Visibility';
+import HttpsIcon from '@mui/icons-material/Https';
+import {
+  Cont, ContUp, Disc, Name, SelectHeader,
+} from './style';
+/**
+   *@component
+   * @param {object} props - default value for radio buttom & myType to set it when change
+   * @return {React.Component} -radio button in  pop up form
+   */
+function RadioBtn(props) {
+  const { myType, type } = props;
+  return (
+    <>
+      <SelectHeader> Type of Community</SelectHeader>
+      <FormControl sx={{ marginBottom: '30px' }}>
+        <RadioGroup
+          aria-labelledby="demo-radio-buttons-group-label"
+          name="radio-buttons-group"
+          id="type"
+          defaultValue={type}
+          onChange={(e) => myType(e.target.value)}
+        >
+          <ContUp condition2="true">
+            <Cont>
+              <FormControlLabel value="Public" control={<Radio />} sx={{ margin: 0 }} />
+              <PersonIcon sx={{ color: 'gray' }} />
+              <Name sx={{ margin: 1 }}>Public</Name>
+            </Cont>
+            <Disc sx={{ pt: 0.5 }}>Anyone can view, post, and comment to this community</Disc>
+          </ContUp>
+          <ContUp>
+            <Cont>
+              <FormControlLabel value="Restricted" control={<Radio />} sx={{ margin: 0 }} />
+              <VisibilityIcon sx={{ color: 'gray' }} />
+              <Name sx={{ margin: 1 }}>Restricted</Name>
+            </Cont>
+            <Disc sx={{ pt: 0.5 }}>
+              Anyone can view this community, but only approved users can post
+            </Disc>
+          </ContUp>
+          <ContUp condition="true">
+            <Cont>
+              <FormControlLabel value="Private" control={<Radio />} sx={{ margin: 0 }} />
+              <HttpsIcon sx={{ color: 'gray' }} />
+              <Name sx={{ margin: 1 }}>Private</Name>
+            </Cont>
+            <Disc sx={{ pt: 0.5 }}>
+              Only approved users can view and submit to this community
+            </Disc>
+          </ContUp>
+        </RadioGroup>
+      </FormControl>
+    </>
+  );
+}
+export default RadioBtn;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Approved_ApproveUser.jsx.html b/docs/components_Moderation_ModUserMng_Approved_ApproveUser.jsx.html new file mode 100644 index 00000000..a46e56b5 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Approved_ApproveUser.jsx.html @@ -0,0 +1,108 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Approved/ApproveUser.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Approved/ApproveUser.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+/* eslint-disable react/jsx-no-constructed-context-values */
+import { Typography } from '@mui/material';
+import ErrorOutlineOutlinedIcon from '@mui/icons-material/ErrorOutlineOutlined';
+import * as React from 'react';
+import {
+  QueueBox, QueueText, ControlBar,
+} from '../styles';
+import { ModMainPage } from '../../ModerationMainPage/styles';
+import ApprovePopUp from './ApproveUserPopUp/ApprovePopUp/ApprovePopUp';
+import { RedditButton } from '../../styles';
+import ApprovedUserList from './NonEmptyApproved/ApprovedUserList/ApprovedUserList';
+
+export const ApproveContext = React.createContext();
+
+/**
+ * the whole page of approved
+ * @component
+ * @return {React.Component} - approved user page
+ */
+
+function Approve() {
+  const [openApprove, setOpenApprove] = React.useState(false);
+
+  const handleClickOpenApprove = () => { setOpenApprove(true); };
+  const handleClickCloseApprove = () => { setOpenApprove(false); };
+  return (
+    <ModMainPage>
+      <ApproveContext.Provider value={{
+        openApprove, handleClickCloseApprove,
+      }}
+      >
+        <ApprovePopUp />
+      </ApproveContext.Provider>
+      <ControlBar>
+        <RedditButton
+          fontSize="14px"
+          padding="0px 24px 0px 24px"
+          fontWeight="bold"
+          variant="contained"
+          onClick={handleClickOpenApprove}
+        >
+          Approve user
+        </RedditButton>
+      </ControlBar>
+      <QueueBox>
+        <QueueText>
+          <Typography variant="h6">Approved users</Typography>
+          <ErrorOutlineOutlinedIcon color="primary" />
+        </QueueText>
+      </QueueBox>
+      <ApprovedUserList />
+    </ModMainPage>
+  );
+}
+
+export default Approve;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Approved_ApproveUserPopUp_ApprovePopUp_ApprovePopUp.jsx.html b/docs/components_Moderation_ModUserMng_Approved_ApproveUserPopUp_ApprovePopUp_ApprovePopUp.jsx.html new file mode 100644 index 00000000..7a467e82 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Approved_ApproveUserPopUp_ApprovePopUp_ApprovePopUp.jsx.html @@ -0,0 +1,103 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Approved/ApproveUserPopUp/ApprovePopUp/ApprovePopUp.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Approved/ApproveUserPopUp/ApprovePopUp/ApprovePopUp.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import * as React from 'react';
+import { Divider, Box } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import { StyledDialog, FooterContainer } from '../../../styles';
+import { ApproveContext } from '../../ApproveUser';
+import Username from '../../../Username/Username';
+import Header from '../../../Header/Header';
+import Footer from '../../../Footer/Footer';
+import { ApprovedUnapprovedUser } from '../../ApprovedServer';
+
+/**
+ * @component Approve popup
+ * @return {React.Component} - approve popup
+ */
+
+function ApprovePopUp() {
+  const { subReddit } = useParams();
+  const {
+    openApprove, handleClickCloseApprove,
+  } = React.useContext(ApproveContext);
+
+  const handleApprove = async () => {
+    const username = document.getElementById('username').value;
+    ApprovedUnapprovedUser(username, subReddit, 'approve');
+  };
+
+  return (
+    <StyledDialog
+      fullScreen
+      height="185px"
+      width="410px"
+      open={openApprove}
+    >
+      <Box>
+        <Header buttonFunction={handleClickCloseApprove} headerText="Add approved user" />
+        <Divider />
+        <Username placeholder="Enter username" />
+      </Box>
+      <FooterContainer>
+        <Footer
+          firstButtonFunction={handleClickCloseApprove}
+          firstButtonText="Cancel"
+          secondButtonFunction={handleApprove}
+          secondButtonText="Add user"
+        />
+      </FooterContainer>
+    </StyledDialog>
+  );
+}
+
+export default ApprovePopUp;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Approved_ApproveUserPopUp_RemovePopUp_RemovePopUp.jsx.html b/docs/components_Moderation_ModUserMng_Approved_ApproveUserPopUp_RemovePopUp_RemovePopUp.jsx.html new file mode 100644 index 00000000..56c526e9 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Approved_ApproveUserPopUp_RemovePopUp_RemovePopUp.jsx.html @@ -0,0 +1,108 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Approved/ApproveUserPopUp/RemovePopUp/RemovePopUp.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Approved/ApproveUserPopUp/RemovePopUp/RemovePopUp.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import * as React from 'react';
+import { Divider, Box, Typography } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import { StyledDialog, FooterContainer } from '../../../styles';
+import { RemoveContext } from '../../NonEmptyApproved/ApprovedUser/ApprovedUser';
+import Header from '../../../Header/Header';
+import Footer from '../../../Footer/Footer';
+import { ApprovedUnapprovedUser } from '../../ApprovedServer';
+
+/**
+ * @component remove popup
+ * @return {React.Component} - remove popup page
+ */
+
+function RemovePopUp(props) {
+  const { userName } = props;
+  const { subReddit } = useParams();
+  const {
+    openRemove, handleClickCloseRemove,
+  } = React.useContext(RemoveContext);
+  const handleUnapprove = () => {
+    ApprovedUnapprovedUser(userName, subReddit, 'disapprove');
+  };
+  return (
+    <StyledDialog
+      fullScreen
+      open={openRemove}
+      width="490px"
+      height="190px"
+    >
+      <Box>
+        <Header buttonFunction={handleClickCloseRemove} headerText="Confirm" />
+        <Divider />
+      </Box>
+      <Box sx={{ padding: '16px' }}>
+        <Typography sx={{ margin: '10px 0px' }}>
+          Are you sure you want to remove
+          {' '}
+          {userName}
+          {' '}
+          as an approved user?
+        </Typography>
+      </Box>
+      <FooterContainer>
+        <Footer
+          firstButtonFunction={handleClickCloseRemove}
+          firstButtonText="Cancel"
+          secondButtonFunction={handleUnapprove}
+          secondButtonText="Remove"
+        />
+      </FooterContainer>
+    </StyledDialog>
+  );
+}
+
+export default RemovePopUp;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Approved_ApprovedServer.js.html b/docs/components_Moderation_ModUserMng_Approved_ApprovedServer.js.html new file mode 100644 index 00000000..41539228 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Approved_ApprovedServer.js.html @@ -0,0 +1,99 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Approved/ApprovedServer.js + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Approved/ApprovedServer.js

+ + + + + + +
+
+
import { useState, useEffect } from 'react';
+import axios from '../../../../services/instance';
+
+/**
+*
+* Function to perfom api request and fetch approved users
+* @param {string} subredditName - name of the subreddit
+* @returns {Array} array of approved users
+*/
+export const ApprovedFetch = (subredditName) => {
+  const [data, setData] = useState([]);
+  const api = `/subreddits/${subredditName}/approved_users`;
+  useEffect(() => {
+    axios.get(api) // fetch api
+      .then((actualData) => {
+        console.log(actualData.data.data);
+        setData(actualData.data.data);
+      })
+      .catch((error) => {
+        if (error.response.status === 401) {
+          window.location.href = './login';
+        }
+
+        console.log(error);
+      });
+  }, [api]);
+  return [data];
+};
+
+/**
+*
+* Function to perfom api request. approve or disprove certain user
+* @param {String} userNmae User name of the user
+* @param {enum} action  enum approve or disprove
+* @param {string} subredditName - name of the subreddit
+* @returns {Array} array of approved users
+*/
+export const ApprovedUnapprovedUser = (userName, subReddit, action) => {
+  axios.post(`/subreddits/${subReddit}/${userName}/${action}/approve_user`).then(async (response) => {
+    console.log(response);
+    if (response.status === 200 || response.status === 201) {
+      console.log('sucess');
+    }
+  }).catch((error) => {
+    console.log(error);
+    console.log(error.response.data.errorMessage);
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Approved_EmptyApproved_EmptyApproved.jsx.html b/docs/components_Moderation_ModUserMng_Approved_EmptyApproved_EmptyApproved.jsx.html new file mode 100644 index 00000000..e5b2760b --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Approved_EmptyApproved_EmptyApproved.jsx.html @@ -0,0 +1,76 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Approved/EmptyApproved/EmptyApproved.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Approved/EmptyApproved/EmptyApproved.jsx

+ + + + + + +
+
+
import { Typography } from '@mui/material';
+
+import CreateOutlinedIcon from '@mui/icons-material/CreateOutlined';
+import { useParams } from 'react-router-dom';
+import { EmptyBox } from '../../styles';
+
+/**
+ * @component empty approve page
+ * @return {React.Component} - empty approved page
+ */
+
+function EmptyApproved() {
+  const { subReddit } = useParams();
+  return (
+    <EmptyBox>
+      <CreateOutlinedIcon sx={{ color: '#7c7c7c' }} fontSize="large" />
+      <Typography variant="h6" color="#7c7c7c">
+        No approved users in r/
+        {' '}
+        {subReddit}
+      </Typography>
+    </EmptyBox>
+  );
+}
+export default EmptyApproved;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Approved_NonEmptyApproved_ApprovedUserList_ApprovedUserList.jsx.html b/docs/components_Moderation_ModUserMng_Approved_NonEmptyApproved_ApprovedUserList_ApprovedUserList.jsx.html new file mode 100644 index 00000000..22af6d82 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Approved_NonEmptyApproved_ApprovedUserList_ApprovedUserList.jsx.html @@ -0,0 +1,119 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Approved/NonEmptyApproved/ApprovedUserList/ApprovedUserList.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Approved/NonEmptyApproved/ApprovedUserList/ApprovedUserList.jsx

+ + + + + + +
+
+
import React from 'react';
+import { useParams } from 'react-router-dom';
+import { ApprovedFetch } from '../../ApprovedServer';
+import ApprovedUser from '../ApprovedUser/ApprovedUser';
+import calculateTime from '../../../../../../utils/calculateTime';
+import SearchBar from '../../../SearchBar/SearchBar';
+import SearchResultBar from '../../../SearchResultBar/SearchResultBar';
+import NoResult from '../../../NoResult/NoResult';
+import EmptyApproved from '../../EmptyApproved/EmptyApproved';
+
+/**
+ * approved user list
+ * @component
+ * @return {React.Component} - approved user list
+ */
+
+function ApprovedUserList() {
+  const [data, setData] = React.useState('');
+  const childToParent = (childData) => {
+    setData(childData);
+  };
+
+  const { subReddit } = useParams();
+  const [ApprovedUsers] = ApprovedFetch(subReddit);
+
+  const [filteredData, setfilteredData] = React.useState([]);
+
+  React.useEffect(() => {
+    setfilteredData(ApprovedUsers.filter((user) => user.user.userName.toLowerCase().includes(data)));
+  }, [data, ApprovedUsers]);
+
+  return (
+    (ApprovedUsers.length === 0) ? (<EmptyApproved />) : (
+      <>
+        <SearchBar childToParent={childToParent} />
+        {
+        (filteredData.length !== 0 && data !== '') && (
+        <SearchResultBar
+          resultNumber={filteredData.length}
+          filteredData={filteredData}
+          childToParent={childToParent}
+        />
+        )
+      }
+        {
+       (filteredData.length === 0 && data !== '') && <NoResult query={data} childToParent={childToParent} />
+      }
+        {
+        filteredData.map((users, index) => {
+          const {
+            user, approvedDate,
+          } = users;
+          return (
+            <ApprovedUser
+              key={`${index + 0}`}
+              userName={user.userName}
+              profilePicture={user.profilePicture}
+              joiningDate={calculateTime(approvedDate)}
+            />
+          );
+        })
+      }
+      </>
+    )
+  );
+}
+
+export default ApprovedUserList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Approved_NonEmptyApproved_ApprovedUser_ApprovedUser.jsx.html b/docs/components_Moderation_ModUserMng_Approved_NonEmptyApproved_ApprovedUser_ApprovedUser.jsx.html new file mode 100644 index 00000000..df5a1461 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Approved_NonEmptyApproved_ApprovedUser_ApprovedUser.jsx.html @@ -0,0 +1,138 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Approved/NonEmptyApproved/ApprovedUser/ApprovedUser.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Approved/NonEmptyApproved/ApprovedUser/ApprovedUser.jsx

+ + + + + + +
+
+
/* eslint-disable react/jsx-no-constructed-context-values */
+/* eslint-disable import/no-cycle */
+import { Box, Typography } from '@mui/material';
+import * as React from 'react';
+import { useNavigate } from 'react-router-dom';
+import {
+  StyledAvatar, UserBar, UserContainer, UserMngButton, UsermngButtonContainer,
+} from '../../../styles';
+
+import RemovePopUp from '../../ApproveUserPopUp/RemovePopUp/RemovePopUp';
+
+export const RemoveContext = React.createContext();
+
+/**
+ * approved user instance
+ * @component
+ * @property  {string} userName username of the approved user
+ * @property  {string} profilePicture link to the profile picture of the approved
+ * @property  {string} joiningDate the date of the approved user to be approved
+ * @return {React.Component} - approved user instance
+ */
+
+function ApprovedUser(props) {
+  const {
+    userName, profilePicture, joiningDate,
+  } = props;
+
+  const navigate = useNavigate();
+
+  // navigate
+  const handleClickUser = (userName) => {
+    navigate(`/user/${userName}`);
+  };
+
+  const [openRemove, setOpenRemove] = React.useState(false);
+
+  const handleClickOpenRemove = () => { setOpenRemove(true); };
+  const handleClickCloseRemove = () => { setOpenRemove(false); };
+
+  return (
+    <UserBar>
+      <RemoveContext.Provider value={{
+        openRemove, handleClickCloseRemove,
+      }}
+      >
+        <RemovePopUp userName={userName} />
+      </RemoveContext.Provider>
+      <UserContainer onClick={() => handleClickUser(userName)}>
+        <StyledAvatar variant="square" src={profilePicture} />
+        <Box>
+          <Typography
+            padding="8px"
+            fontSize="15px"
+            fontWeight="bold"
+          >
+            {userName}
+          </Typography>
+        </Box>
+      </UserContainer>
+      <Box sx={{ display: 'flex', width: '100%' }}>
+        <Typography
+          padding="8px"
+          fontSize="12px"
+          color="#878A8C"
+        >
+          {joiningDate}
+        </Typography>
+      </Box>
+      <UsermngButtonContainer>
+        <UserMngButton
+          disableRipple
+          disableFocusRipple
+        >
+          Send message
+        </UserMngButton>
+        <UserMngButton
+          disableRipple
+          disableFocusRipple
+          onClick={handleClickOpenRemove}
+        >
+          Remove
+        </UserMngButton>
+      </UsermngButtonContainer>
+    </UserBar>
+  );
+}
+export default ApprovedUser;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_BanUser.jsx.html b/docs/components_Moderation_ModUserMng_Banned_BanUser.jsx.html new file mode 100644 index 00000000..486ec699 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_BanUser.jsx.html @@ -0,0 +1,108 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/BanUser.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/BanUser.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+/* eslint-disable react/jsx-no-constructed-context-values */
+import { Typography } from '@mui/material';
+import ErrorOutlineOutlinedIcon from '@mui/icons-material/ErrorOutlineOutlined';
+import * as React from 'react';
+import {
+  QueueBox, QueueText, ControlBar,
+} from '../styles';
+import { ModMainPage } from '../../ModerationMainPage/styles';
+import BanPopUp from './BanUserPopUp/BanPopUp/BanPopUp';
+import { RedditButton } from '../../styles';
+import BannedUserList from './NonEmptyBanned/BannedUserList/BannedUserList';
+
+export const BanContext = React.createContext();
+
+/**
+ * the whole page of banned
+ * @component
+ * @return {React.Component} - banned user page
+ */
+
+function Ban() {
+  const [openBan, setOpenBan] = React.useState(false);
+
+  const handleClickOpenBan = () => { setOpenBan(true); };
+  const handleClickCloseBan = () => { setOpenBan(false); };
+  return (
+    <ModMainPage>
+      <BanContext.Provider value={{
+        openBan, handleClickCloseBan,
+      }}
+      >
+        <BanPopUp />
+      </BanContext.Provider>
+      <ControlBar>
+        <RedditButton
+          fontSize="14px"
+          padding="0px 24px 0px 24px"
+          fontWeight="bold"
+          variant="contained"
+          onClick={handleClickOpenBan}
+        >
+          Ban user
+        </RedditButton>
+      </ControlBar>
+      <QueueBox>
+        <QueueText>
+          <Typography variant="h6">Banned users</Typography>
+          <ErrorOutlineOutlinedIcon color="primary" />
+        </QueueText>
+      </QueueBox>
+      <BannedUserList />
+    </ModMainPage>
+  );
+}
+
+export default Ban;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanFooter_BanFooter.jsx.html b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanFooter_BanFooter.jsx.html new file mode 100644 index 00000000..58e8f0b2 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanFooter_BanFooter.jsx.html @@ -0,0 +1,101 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/BanFooter/BanFooter.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/BanFooter/BanFooter.jsx

+ + + + + + +
+
+
import { Typography, Box } from '@mui/material';
+import { StyledBox } from './styles';
+import { RedditButton } from '../../../../styles';
+
+/**
+ * Ban Footer
+ * @component
+ * @property  {function} handleClickCloseBan close the popup when a button is clicked
+ * @property  {function} handleBan operate the function of banning user and send data to backend when a button is clicked
+ * @return {React.Component} - Ban Footer component
+ */
+
+function BanFooter(props) {
+  const { handleClickCloseBan, handleBan } = props;
+
+  return (
+    <StyledBox>
+      <Typography>
+        โ€ข Visible to banned user
+      </Typography>
+      <Box>
+        <RedditButton
+          fontSize="15px"
+          padding="0px 24px 0px 24px"
+          fontWeight="bold"
+          variant="outlined"
+          onClick={handleClickCloseBan}
+          disableRipple
+          disableFocusRipple
+        >
+          Cancel
+        </RedditButton>
+        <RedditButton
+          sx={{ marginLeft: 1 }}
+          fontSize="14px"
+          padding="0px 24px 0px 24px"
+          fontWeight="bold"
+          variant="contained"
+          disableRipple
+          disableFocusRipple
+          onClick={handleBan}
+        >
+          Ban user
+        </RedditButton>
+      </Box>
+    </StyledBox>
+  );
+}
+
+export default BanFooter;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanMessage_BanMessage.jsx.html b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanMessage_BanMessage.jsx.html new file mode 100644 index 00000000..a9fa4107 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanMessage_BanMessage.jsx.html @@ -0,0 +1,95 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/BanMessage/BanMessage.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/BanMessage/BanMessage.jsx

+ + + + + + +
+
+
import * as React from 'react';
+import { Typography } from '@mui/material';
+import { StyledBox } from './styles';
+import { FullDiscTextArea, Count } from '../../../../Rules/AddRule/style';
+
+/**
+ * BanMessage
+ * @component
+ * @property  {string} punishReason text to explain more details about why this user is banned if available
+ * @return {React.Component} - BanMessageComponent (text area)
+ */
+
+function BanMessage(props) {
+  const { punishReason } = props;
+  const [count, setCount] = React.useState(5000);
+  const check = (e) => {
+    const ele = e?.target?.value;
+    if (5000 - ele.length >= 0) { setCount(5000 - ele.length); }
+  };
+  return (
+    <StyledBox>
+      <Typography>Note to include in ban message โ€ข</Typography>
+      <FullDiscTextArea
+        defaultValue={punishReason}
+        id="banMessage"
+        placeholder="Reason they were banned"
+        onChange={check}
+        onInput={(e) => {
+          // eslint-disable-next-line radix
+          e.target.value = e.target.value.slice(0, 5000);
+        }}
+      />
+      <Count
+        condition={(count === 0).toString()}
+      >
+        {count}
+        {' '}
+        Characters remaining
+      </Count>
+    </StyledBox>
+  );
+}
+
+export default BanMessage;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanNote_BanNote.jsx.html b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanNote_BanNote.jsx.html new file mode 100644 index 00000000..ca42025a --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanNote_BanNote.jsx.html @@ -0,0 +1,91 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/BanNote/BanNote.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/BanNote/BanNote.jsx

+ + + + + + +
+
+
import * as React from 'react';
+import { TextField } from '@mui/material';
+import { StyledBox, StyledFont } from './styles';
+
+/**
+ * BanNote
+ * @component
+ * @property  {string} note a note from the moderator about the banned user
+ * @return {React.Component} - Bannote (text field)
+ */
+
+function BanNote(props) {
+  const { note } = props;
+  const CHARACTER_LIMIT = 300;
+  const [values, setValues] = React.useState({
+    name: note,
+  });
+  const handleChangeCharNum = (name) => (event) => {
+    setValues({ ...values, [name]: event.target.value });
+  };
+  return (
+    <StyledBox>
+      <StyledFont>MOD NOTE</StyledFont>
+      <TextField
+        id="banNote"
+        placeholder="Mod Note"
+        size="small"
+        fullWidth
+        inputProps={{
+          maxLength: CHARACTER_LIMIT,
+        }}
+        value={values.name}
+        helperText={`${CHARACTER_LIMIT - values.name.length} Characters remaining`}
+        onChange={handleChangeCharNum('name')}
+      />
+    </StyledBox>
+  );
+}
+
+export default BanNote;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanPeriod_BanPeriod.jsx.html b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanPeriod_BanPeriod.jsx.html new file mode 100644 index 00000000..639339ee --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanPeriod_BanPeriod.jsx.html @@ -0,0 +1,112 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/BanPeriod/BanPeriod.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/BanPeriod/BanPeriod.jsx

+ + + + + + +
+
+
import * as React from 'react';
+import {
+  FormControl, FormControlLabel, TextField, Checkbox, Box,
+} from '@mui/material';
+import { StyledBox, StyledFont } from './styles';
+
+/**
+ * Ban period
+ * @component
+ * @property  {string} duration the period of banning the user its range is from 1 to 999 or parmenant
+ * @return {React.Component} - Ban period component
+ */
+
+function BanPeriod(props) {
+  const { duration } = props;
+  const [checked, setChecked] = React.useState(duration === -1);
+  const [banPeriod, setbanPeriod] = React.useState((duration === -1) ? 1 : duration);
+
+  return (
+    <>
+      <StyledFont>HOW LONG?</StyledFont>
+      <StyledBox>
+        <Box>
+          <TextField
+            id="duration"
+            type="number"
+            inputProps={{ min: 1, max: 999 }}
+            disabled={checked}
+            value={(checked) ? '' : banPeriod}
+            size="small"
+            sx={{ width: '75px' }}
+            focused
+            onChange={(event) => setbanPeriod(event.target.value)}
+          />
+          <TextField
+            defaultValue="Days"
+            disabled
+            size="small"
+            sx={{ width: '75px' }}
+          />
+        </Box>
+        <FormControl component="fieldset">
+          <FormControlLabel
+            control={(
+              <Checkbox
+                checked={checked}
+                onClick={() => { setChecked(!checked); }}
+                disableRipple
+                disableFocusRipple
+              />
+)}
+            label="Permanent"
+            labelPlacement="end"
+          />
+        </FormControl>
+      </StyledBox>
+    </>
+  );
+}
+
+export default BanPeriod;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanPopUp_BanPopUp.jsx.html b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanPopUp_BanPopUp.jsx.html new file mode 100644 index 00000000..4255738f --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanPopUp_BanPopUp.jsx.html @@ -0,0 +1,111 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/BanPopUp/BanPopUp.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/BanPopUp/BanPopUp.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import * as React from 'react';
+import { Divider, Box } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import { StyledDialog } from '../../../styles';
+import { BanContext } from '../../BanUser';
+import Header from '../../../Header/Header';
+import Username from '../../../Username/Username';
+import BanReason from '../BanReason/BanReason';
+import BanNote from '../BanNote/BanNote';
+import BanPeriod from '../BanPeriod/BanPeriod';
+import BanMessage from '../BanMessage/BanMessage';
+import BanFooter from '../BanFooter/BanFooter';
+import { banUnbanUser } from '../banServer';
+
+/**
+ * Ban popup
+ * @component
+ * @return {React.Component} - Ban popup component
+ */
+
+function BanPopUp() {
+  const { subReddit } = useParams();
+  const {
+    openBan, handleClickCloseBan,
+  } = React.useContext(BanContext);
+
+  const handleBan = async () => {
+    const userName = document.getElementById('username').value;
+    const reason = document.getElementById('reason').textContent;
+    const banNote = document.getElementById('banNote').value;
+    const banMessage = document.getElementById('banMessage').value;
+    const duration = document.getElementById('duration').value;
+    banUnbanUser(userName, subReddit, 'ban', reason, banNote, banMessage, duration);
+  };
+  return (
+    <StyledDialog
+      fullScreen
+      open={openBan}
+      width="538px"
+      height="625px"
+    >
+      <Box>
+        <Header buttonFunction={handleClickCloseBan} headerText="Ban a user:" />
+        <Divider />
+        <Username placeholder="u/username" />
+        <BanReason punishType="Spam" />
+        <BanNote note="" />
+        <BanPeriod duration={-1} />
+      </Box>
+      <Box sx={{ backgroundColor: '#edeff1 ', height: '100%' }}>
+        <BanMessage />
+        <BanFooter handleClickCloseBan={handleClickCloseBan} handleBan={handleBan} />
+      </Box>
+
+    </StyledDialog>
+  );
+}
+
+export default BanPopUp;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanReason_BanReason.jsx.html b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanReason_BanReason.jsx.html new file mode 100644 index 00000000..34003c82 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_BanReason_BanReason.jsx.html @@ -0,0 +1,93 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/BanReason/BanReason.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/BanReason/BanReason.jsx

+ + + + + + +
+
+
import { Divider, Select } from '@mui/material';
+import * as React from 'react';
+import {
+  StyledBox, StyledFont, StyledMenuItem,
+} from './styles';
+
+/**
+ * Ban reason
+ * @component
+ * @property  {enum} punishType it is the bunish type if the user is spam or Threatening, Harassing, Or Inciting Violence or Personal And Confidential Information or other reason
+ * @return {React.Component} - approved user instance
+ */
+
+function BanReason(props) {
+  const { punishType } = props;
+  const [punishTypeState, setpunishType] = React.useState(punishType);
+
+  const handleChangeComboBox = (event) => {
+    setpunishType(event.target.value);
+  };
+  return (
+    <StyledBox>
+      <StyledFont>REASON FOR BAN</StyledFont>
+      <Select
+        id="reason"
+        fullWidth
+        value={punishTypeState}
+        onChange={handleChangeComboBox}
+        size="small"
+      >
+        <StyledMenuItem value="Spam">Spam</StyledMenuItem>
+        <Divider sx={{ margin: '0px !important' }} />
+        <StyledMenuItem value="Personal And Confidential Information">Personal And Confidential Information</StyledMenuItem>
+        <Divider sx={{ margin: '0px !important' }} />
+        <StyledMenuItem value="Threatening, Harassing, Or Inciting Violence">Threatening, Harassing, Or Inciting Violence</StyledMenuItem>
+        <Divider sx={{ margin: '0px !important' }} />
+        <StyledMenuItem value="Other">Other</StyledMenuItem>
+      </Select>
+    </StyledBox>
+  );
+}
+export default BanReason;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_EditBanFooter_EditBanFooter.jsx.html b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_EditBanFooter_EditBanFooter.jsx.html new file mode 100644 index 00000000..cf1deaa0 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_EditBanFooter_EditBanFooter.jsx.html @@ -0,0 +1,112 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/EditBanFooter/EditBanFooter.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/EditBanFooter/EditBanFooter.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import CheckCircleIcon from '@mui/icons-material/CheckCircle';
+import { StyledBox } from './styles';
+import { RedditButton } from '../../../../styles';
+import { UserMngButton } from '../../../styles';
+
+/**
+ * EditBan popup footer
+ * @component
+ * @property  {function} handleClickCloseBan close the popup
+ * @property  {function} handleUnban unban user and send data to the backend
+ * @property  {function} handleEditBan edit banned user data from the duration of be panned to the reason and the ban message etc
+ * @return {React.Component} - EditBan popup foooter
+ */
+
+function EditBanFooter(props) {
+  const { handleClickCloseBan, handleUnban, handleEditBan } = props;
+  return (
+    <StyledBox>
+      <UserMngButton
+        fontSize="15px"
+        padding="0px 24px 0px 24px"
+        fontWeight="bold"
+        disableRipple
+        disableFocusRipple
+        sx={{ color: 'red' }}
+        onClick={handleUnban}
+        startIcon={<CheckCircleIcon sx={{ color: 'Red' }} />}
+      >
+        Unban
+      </UserMngButton>
+      <Box>
+        <RedditButton
+          fontSize="15px"
+          padding="0px 24px 0px 24px"
+          fontWeight="bold"
+          variant="outlined"
+          onClick={handleClickCloseBan}
+          disableRipple
+          disableFocusRipple
+        >
+          Cancel
+        </RedditButton>
+        <RedditButton
+          sx={{ marginLeft: 1 }}
+          fontSize="14px"
+          padding="0px 24px 0px 24px"
+          fontWeight="bold"
+          variant="contained"
+          disableRipple
+          disableFocusRipple
+          onClick={handleEditBan}
+        >
+          Edit
+        </RedditButton>
+      </Box>
+    </StyledBox>
+  );
+}
+
+export default EditBanFooter;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_EditBanHeader_EditBanHeader.jsx.html b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_EditBanHeader_EditBanHeader.jsx.html new file mode 100644 index 00000000..2c3e381e --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_EditBanHeader_EditBanHeader.jsx.html @@ -0,0 +1,82 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/EditBanHeader/EditBanHeader.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/EditBanHeader/EditBanHeader.jsx

+ + + + + + +
+
+
import { Typography } from '@mui/material';
+import CloseIcon from '@mui/icons-material/Close';
+import StyledBox from './styles';
+
+/**
+ * EditBan popup header
+ * @component
+ * @property  {function} handleClickCloseBan close the popup
+ * @property  {string} userName the username of banned user
+ * @return {React.Component} - EditBan popup header
+ */
+
+function EditBanHaeder(props) {
+  const { handleClickCloseBan, userName } = props;
+  return (
+    <StyledBox>
+      <Typography
+        fontWeight={600}
+      >
+        Edit ban for: u/
+        {userName}
+      </Typography>
+      <CloseIcon
+        sx={{ cursor: 'pointer' }}
+        onClick={handleClickCloseBan}
+      />
+    </StyledBox>
+  );
+}
+
+export default EditBanHaeder;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_EditBanPopUp_EditBanPopUp.jsx.html b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_EditBanPopUp_EditBanPopUp.jsx.html new file mode 100644 index 00000000..073bc524 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_EditBanPopUp_EditBanPopUp.jsx.html @@ -0,0 +1,119 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/EditBanPopUp/EditBanPopUp.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/EditBanPopUp/EditBanPopUp.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import * as React from 'react';
+import { Divider, Box } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import { StyledDialog } from '../../../styles';
+import EditBanHeader from '../EditBanHeader/EditBanHeader';
+import BanReason from '../BanReason/BanReason';
+import BanNote from '../BanNote/BanNote';
+import BanPeriod from '../BanPeriod/BanPeriod';
+import BanMessage from '../BanMessage/BanMessage';
+import EditBanFooter from '../EditBanFooter/EditBanFooter';
+import { EditBanContext } from '../../NonEmptyBanned/BannedUser/BannedUser';
+import { banUnbanUser, Editban } from '../banServer';
+
+/**
+ * EditBan popup
+ * @component
+ * @property  {string} userName username of banned user
+ * @property  {string} note the moderator note about the banned user
+ * @property  {string} punishReason more details from the moderator about the banned user
+ * @property  {enum} punishType enum explain why this user is banned ( spam of threatining ... etc)
+ * @property  {string} duration the period that the user is banned it ranges from 0 to 999 or may be permenant
+ * @return {React.Component} - EditBan popup
+ */
+
+function EditBanPopUp(props) {
+  const {
+    userName, note, punishReason, punishType, duration,
+  } = props;
+  const { subReddit } = useParams();
+  const handleUnban = () => {
+    banUnbanUser(userName, subReddit, 'unban', '', '', '', '');
+  };
+
+  const handleEditBan = () => {
+    const reason = document.getElementById('reason').textContent;
+    const banNote = document.getElementById('banNote').value;
+    const banMessage = document.getElementById('banMessage').value;
+    const duration = document.getElementById('duration').value;
+    Editban(userName, subReddit, reason, banNote, banMessage, duration);
+  };
+
+  const {
+    openEditBan, handleClickCloseEditBan,
+  } = React.useContext(EditBanContext);
+  return (
+    <StyledDialog
+      fullScreen
+      open={openEditBan}
+      width="538px"
+      height="545px"
+    >
+      <Box>
+        <EditBanHeader handleClickCloseBan={handleClickCloseEditBan} userName={userName} />
+        <Divider />
+        <BanReason punishType={punishType} />
+        <BanNote note={note} />
+        <BanPeriod duration={duration} />
+      </Box>
+      <Box sx={{ backgroundColor: '#edeff1 ', height: '100%' }}>
+        <BanMessage punishReason={punishReason} />
+        <EditBanFooter handleClickCloseBan={handleClickCloseEditBan} handleUnban={handleUnban} handleEditBan={handleEditBan} />
+      </Box>
+    </StyledDialog>
+  );
+}
+
+export default EditBanPopUp;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_banServer.js.html b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_banServer.js.html new file mode 100644 index 00000000..b4ee3766 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_BanUserPopUp_banServer.js.html @@ -0,0 +1,111 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/banServer.js + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/BanUserPopUp/banServer.js

+ + + + + + +
+
+
// services
+import axios from '../../../../../services/instance';
+
+/**
+*
+* Function to perfom api request. ban or unban certain user
+* @param {String} userNmae User name of the user
+* @param {enum} action  enum ban or unban
+* @param {string} subredditName - name of the subreddit
+* @param {enum} punishType - indicates why this user is banned
+* @param {string} note - note from the moderator about this user
+* @param {string} reason - more explanation about this user to be banned like reason etc..
+* @param {string} banPeriod - the period of banning certain user it rages from 0 to 999 or can be permanently
+* @returns void
+*/
+export const banUnbanUser = (userName, subReddit, action, punishType, note, Reason, banPeriod) => {
+  axios.post(`/subreddits/${subReddit}/Ban_settings/${action}/${userName}`, JSON.stringify({
+    punish_type: punishType,
+    Note: note,
+    punishReason: Reason,
+    duration: banPeriod,
+  })).then((response) => {
+    console.log(response);
+    if (response.status === 200 || response.status === 201) {
+      console.log('sucess');
+    }
+  }).catch((error) => {
+    console.log(error);
+    console.log(error.response.data.errorMessage);
+  });
+};
+
+/**
+*
+* Function to perfom api request. edit banned user data
+* @param {String} userNmae User name of the user
+* @param {string} subredditName - name of the subreddit
+* @param {enum} punishType - indicates why this user is banned
+* @param {string} note - note from the moderator about this user
+* @param {string} reason - more explanation about this user to be banned like reason etc..
+* @param {string} banPeriod - the period of banning certain user it rages from 0 to 999 or can be permanently
+* @returns void
+*/
+export const Editban = (username, subReddit, punishType, note, Reason, banPeriod) => {
+  axios.patch(`/subreddits/${subReddit}/banned`, JSON.stringify({
+    userName: username,
+    punish_type: punishType,
+    Note: note,
+    punishReason: Reason,
+    duration: banPeriod,
+  })).then((response) => {
+    console.log(response);
+    if (response.status === 200 || response.status === 201) {
+      console.log('sucess');
+    }
+  }).catch((error) => {
+    console.log(error);
+    console.log(error.response.data.errorMessage);
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_EmptyBanned_EmptyBanned.jsx.html b/docs/components_Moderation_ModUserMng_Banned_EmptyBanned_EmptyBanned.jsx.html new file mode 100644 index 00000000..c32d5cfc --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_EmptyBanned_EmptyBanned.jsx.html @@ -0,0 +1,75 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/EmptyBanned/EmptyBanned.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/EmptyBanned/EmptyBanned.jsx

+ + + + + + +
+
+
import { Typography } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import NotInterestedIcon from '@mui/icons-material/NotInterested';
+import { EmptyBox } from '../../styles';
+
+/**
+ * empty ban page
+ * @component
+ * @return {React.Component} - empty ban page component
+ */
+
+function EmptyBanned() {
+  const { subReddit } = useParams();
+  return (
+    <EmptyBox>
+      <NotInterestedIcon sx={{ color: '#7c7c7c' }} fontSize="large" />
+      <Typography variant="h6" color="#7c7c7c">
+        No banned users in r/
+        {subReddit}
+      </Typography>
+    </EmptyBox>
+  );
+}
+export default EmptyBanned;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_NonEmptyBanned_BannedUserList_BannedServer.js.html b/docs/components_Moderation_ModUserMng_Banned_NonEmptyBanned_BannedUserList_BannedServer.js.html new file mode 100644 index 00000000..6c686b42 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_NonEmptyBanned_BannedUserList_BannedServer.js.html @@ -0,0 +1,81 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/NonEmptyBanned/BannedUserList/BannedServer.js + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/NonEmptyBanned/BannedUserList/BannedServer.js

+ + + + + + +
+
+
import { useState, useEffect } from 'react';
+import axios from '../../../../../../services/instance';
+
+/**
+*
+* Function to perfom api request. fetch banned user list
+* @param {string} subredditName - name of the subreddit
+* @returns {Array} array of banned users
+*/
+
+export const bannedFetch = (subredditName) => {
+  const [data, setData] = useState([]);
+
+  const api = `/subreddits/${subredditName}/banned`;
+  useEffect(() => {
+    axios.get(api) // fetch api
+      .then((actualData) => {
+        console.log(actualData.data);
+        setData(actualData.data.data.filter((users) => users.type.includes('banned')));
+      })
+      .catch((error) => {
+        if (error.response.status === 401) {
+          window.location.href = './login';
+        }
+
+        console.log(error);
+      });
+  }, [api]);
+  return [data];
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_NonEmptyBanned_BannedUserList_BannedUserList.jsx.html b/docs/components_Moderation_ModUserMng_Banned_NonEmptyBanned_BannedUserList_BannedUserList.jsx.html new file mode 100644 index 00000000..55016984 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_NonEmptyBanned_BannedUserList_BannedUserList.jsx.html @@ -0,0 +1,122 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/NonEmptyBanned/BannedUserList/BannedUserList.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/NonEmptyBanned/BannedUserList/BannedUserList.jsx

+ + + + + + +
+
+
import React from 'react';
+import { useParams } from 'react-router-dom';
+import { bannedFetch } from './BannedServer';
+import BannedUser from '../BannedUser/BannedUser';
+import calculateTime from '../../../../../../utils/calculateTime';
+import SearchBar from '../../../SearchBar/SearchBar';
+import SearchResultBar from '../../../SearchResultBar/SearchResultBar';
+import NoResult from '../../../NoResult/NoResult';
+import EmptyBanned from '../../EmptyBanned/EmptyBanned';
+
+/**
+ * banned user list
+ * @component
+ * @return {React.Component} - banned user list
+ */
+
+function BannedUserList() {
+  const [data, setData] = React.useState('');
+  const childToParent = (childData) => {
+    setData(childData);
+  };
+
+  const { subReddit } = useParams();
+  const [BannedUsers] = bannedFetch(subReddit);
+  const [filteredData, setfilteredData] = React.useState([]);
+
+  React.useEffect(() => {
+    setfilteredData(BannedUsers?.filter((users) => users.user.userName.toLowerCase().includes(data)));
+  }, [data, BannedUsers]);
+
+  return (
+    (BannedUsers.length === 0) ? (<EmptyBanned />) : (
+      <>
+        <SearchBar childToParent={childToParent} />
+        {
+        (filteredData.length !== 0 && data !== '') && (
+        <SearchResultBar
+          resultNumber={filteredData.length}
+          filteredData={filteredData}
+          childToParent={childToParent}
+        />
+        )
+        }
+        {
+        (filteredData.length === 0 && data !== '') && <NoResult query={data} childToParent={childToParent} />
+        }
+        {
+      filteredData.map((users, index) => {
+        const {
+          user, banInfo,
+        } = users;
+        return (
+          <BannedUser
+            key={`${index + 0}`}
+            userName={user.userName}
+            profilePicture={user.profilePicture}
+            banDate={calculateTime(banInfo.banDate)}
+            punishType={banInfo.punish_type}
+            note={banInfo.Note}
+            punishReason={banInfo.punishReason}
+            duration={banInfo.duration}
+          />
+        );
+      })
+    }
+      </>
+    )
+  );
+}
+
+export default BannedUserList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_NonEmptyBanned_BannedUser_BannedUser.jsx.html b/docs/components_Moderation_ModUserMng_Banned_NonEmptyBanned_BannedUser_BannedUser.jsx.html new file mode 100644 index 00000000..eaa208a1 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_NonEmptyBanned_BannedUser_BannedUser.jsx.html @@ -0,0 +1,178 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/NonEmptyBanned/BannedUser/BannedUser.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/NonEmptyBanned/BannedUser/BannedUser.jsx

+ + + + + + +
+
+
/* eslint-disable react/jsx-no-constructed-context-values */
+/* eslint-disable import/no-cycle */
+import { Box, Typography } from '@mui/material';
+import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
+import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
+import { useNavigate } from 'react-router-dom';
+import * as React from 'react';
+import {
+  UserBar, UserContainer, UserMngButton, StyledAvatar, UsermngButtonContainer, TextContainer,
+} from '../../../styles';
+
+import MoreDetails from '../MoreDetails/MoreDetails';
+import EditBanPopUp from '../../BanUserPopUp/EditBanPopUp/EditBanPopUp';
+
+export const EditBanContext = React.createContext();
+
+/**
+ * Banned user instace
+ * @component
+ * @property  {string} username username of banned user
+ * @property  {string} profilePicture link to banned user profile picture
+ * @property  {string} banDate the date that the user is banned at
+ * @property {enum} punishType explain why this user is banned (spam or threatining etc...)
+ * @property {string} note note from the moderator about the banned user
+ * @property {string} punishReason extra details about the banned user
+ * @property {string} duration the duration ban for the banned user it ranges from 0 to 999 and can be permenant
+ * @return {React.Component} - Banned user instace component
+ */
+
+function BannedUser(props) {
+  const {
+    userName, profilePicture, banDate, punishType, note, punishReason, duration,
+  } = props;
+
+  const navigate = useNavigate();
+
+  // navigate
+  const handleClickUser = (userName) => {
+    navigate(`/user/${userName}`);
+  };
+
+  const [openEditBan, setOpenEditBan] = React.useState(false);
+
+  const handleClickOpenEditBan = () => { setOpenEditBan(true); };
+  const handleClickCloseEditBan = () => { setOpenEditBan(false); };
+
+  const [isOpened, setOpen] = React.useState(false);
+  const handleClick = () => {
+    setOpen(!isOpened);
+  };
+  return (
+    <>
+      <UserBar>
+        <EditBanContext.Provider value={{
+          openEditBan, handleClickCloseEditBan,
+        }}
+        >
+          <EditBanPopUp
+            userName={userName}
+            note={note}
+            punishReason={punishReason}
+            punishType={punishType}
+            duration={duration}
+          />
+        </EditBanContext.Provider>
+        <UserContainer onClick={() => handleClickUser(userName)}>
+          <StyledAvatar src={profilePicture} variant="square" />
+          <Box>
+            <Typography
+              padding="8px"
+              fontSize="15px"
+              fontWeight="bold"
+            >
+              {userName}
+            </Typography>
+          </Box>
+        </UserContainer>
+        <TextContainer>
+          <Typography
+            padding="8px"
+            fontSize="12px"
+            color="#878A8C"
+          >
+            {banDate}
+            {' '}
+            (
+            {(duration === -1) ? 'permenant' : `${duration} days left`}
+            )
+          </Typography>
+          <Typography
+            padding="8px"
+            fontSize="12px"
+            color="#878A8C"
+          >
+            โ€ข
+          </Typography>
+          <Typography
+            padding="8px"
+            fontSize="12px"
+            color="#878A8C"
+          >
+            {punishType}
+          </Typography>
+        </TextContainer>
+        <UsermngButtonContainer>
+          <UserMngButton
+            disableRipple
+            disableFocusRipple
+            onClick={handleClickOpenEditBan}
+          >
+            Edit
+          </UserMngButton>
+          <UserMngButton
+            disableRipple
+            disableFocusRipple
+            onClick={handleClick}
+            endIcon={(isOpened) ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
+          >
+            More Details
+          </UserMngButton>
+        </UsermngButtonContainer>
+      </UserBar>
+      <MoreDetails modNote={note} bannedFor={punishReason} isOpened={isOpened} />
+    </>
+  );
+}
+export default BannedUser;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Banned_NonEmptyBanned_MoreDetails_MoreDetails.jsx.html b/docs/components_Moderation_ModUserMng_Banned_NonEmptyBanned_MoreDetails_MoreDetails.jsx.html new file mode 100644 index 00000000..87ca91e6 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Banned_NonEmptyBanned_MoreDetails_MoreDetails.jsx.html @@ -0,0 +1,114 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Banned/NonEmptyBanned/MoreDetails/MoreDetails.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Banned/NonEmptyBanned/MoreDetails/MoreDetails.jsx

+ + + + + + +
+
+
import { Box, Typography } from '@mui/material';
+import { StyledDetails } from '../../../styles';
+
+/**
+ * more datails tab
+ * @component
+ * @property  {boolean} isOpened determine the state of more details tab to be showed or hidden
+ * @property {enum} bannedFor explain why this user is banned (spam or threatining etc...)
+ * @property {string} modNote note from the moderator about the banned user
+ * @return {React.Component} - more details tab
+ */
+
+function MoreDetails(props) {
+  const { modNote, bannedFor, isOpened } = props;
+  return (
+    <StyledDetails
+      display={(isOpened) ? 'flex' : 'none'}
+    >
+      <Box padding="16px">
+        {(modNote !== '') && (
+          <Box display="flex" alignItems="center" paddingBottom="10px">
+            <Typography
+              fontSize="10px"
+              color="#878A8C"
+              fontWeight={700}
+              marginRight="3px"
+              textTransform="uppercase"
+            >
+              mod note:
+            </Typography>
+            <Typography
+              fontSize="12px"
+              color="#1C1C1C"
+              paddingBottom="2px"
+            >
+              {modNote}
+            </Typography>
+          </Box>
+        )}
+        <Box display="flex" alignItems="center">
+          <Typography
+            fontSize="10px"
+            color="#878a8c"
+            fontWeight={700}
+            marginRight="3px"
+            textTransform="uppercase"
+          >
+            banned for:
+          </Typography>
+          <Typography
+            fontSize="12px"
+            color="#1C1C1C"
+            paddingBottom="2px"
+          >
+            {bannedFor}
+          </Typography>
+        </Box>
+      </Box>
+    </StyledDetails>
+  );
+}
+
+export default MoreDetails;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Footer_Footer.jsx.html b/docs/components_Moderation_ModUserMng_Footer_Footer.jsx.html new file mode 100644 index 00000000..6e8c182b --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Footer_Footer.jsx.html @@ -0,0 +1,98 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Footer/Footer.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Footer/Footer.jsx

+ + + + + + +
+
+
import { StyledBox } from './styles';
+import { RedditButton } from '../../styles';
+
+/**
+ * Footer of popups for user management section
+ * @component
+ * @property {function} firstButtonFunction the first button functionality
+ * @property {string} firstButtonText the first button label
+ * @property {function} secondButtonFuncion the second button functionality
+ * @property {string} secondButtonText the second button label
+ * @return {React.Component} - Footer component
+ */
+
+function Footer(props) {
+  const {
+    firstButtonFunction, firstButtonText, secondButtonFunction, secondButtonText,
+  } = props;
+  return (
+    <StyledBox>
+      <RedditButton
+        fontSize="15px"
+        padding="0px 24px 0px 24px"
+        fontWeight="bold"
+        variant="outlined"
+        onClick={firstButtonFunction}
+        disableRipple
+        disableFocusRipple
+      >
+        {firstButtonText}
+      </RedditButton>
+      <RedditButton
+        sx={{ marginLeft: 1 }}
+        fontSize="14px"
+        padding="0px 24px 0px 24px"
+        fontWeight="bold"
+        variant="contained"
+        disableRipple
+        disableFocusRipple
+        onClick={secondButtonFunction}
+      >
+        {secondButtonText}
+      </RedditButton>
+    </StyledBox>
+  );
+}
+
+export default Footer;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Header_Header.jsx.html b/docs/components_Moderation_ModUserMng_Header_Header.jsx.html new file mode 100644 index 00000000..b21af6c6 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Header_Header.jsx.html @@ -0,0 +1,84 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Header/Header.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Header/Header.jsx

+ + + + + + +
+
+
import { Typography } from '@mui/material';
+import CloseIcon from '@mui/icons-material/Close';
+import StyledBox from './styles';
+
+/**
+ * Header of popups for user management section
+ * @component
+ * @property {function} buttonFunction the button functionality
+ * @property {string} headerText the label of the header
+ * @return {React.Component} - Header component
+ */
+
+function Header(props) {
+  const { buttonFunction, headerText } = props;
+  return (
+    <StyledBox>
+      <Typography
+        color="#1C1C1C"
+        fontSize="16px"
+        fontWeight={600}
+      >
+        {headerText}
+
+      </Typography>
+      <CloseIcon
+        sx={{ cursor: 'pointer' }}
+        onClick={buttonFunction}
+      />
+    </StyledBox>
+  );
+}
+
+export default Header;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Moderators_EditPopUp_EditPopUp.jsx.html b/docs/components_Moderation_ModUserMng_Moderators_EditPopUp_EditPopUp.jsx.html new file mode 100644 index 00000000..5f527098 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Moderators_EditPopUp_EditPopUp.jsx.html @@ -0,0 +1,118 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Moderators/EditPopUp/EditPopUp.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Moderators/EditPopUp/EditPopUp.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import * as React from 'react';
+import { Divider, Box, Typography } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import { StyledDialog, FooterContainer } from '../../styles';
+import { EditContext } from '../NonEmptyModerator/NonEmptyModerator';
+import Header from '../../Header/Header';
+import Foooter from '../../Footer/Footer';
+import Permissions from '../Permissions/Persmissions';
+import { editMod } from './editServer';
+
+/**
+ * Edit popup for moderator page
+ * @component
+ * @property {string} username username of the moderator
+ * @return {React.Component} - edit moderator popup component
+ */
+
+function EditPopUp(props) {
+  const { userName } = props;
+  const { subReddit } = useParams();
+
+  const handleEdit = async () => {
+    const everything = document.getElementById('everything').checked;
+    const manageUsers = document.getElementById('manage_users').checked;
+    const manageSettings = document.getElementById('manage_settings').checked;
+    const manageFlair = document.getElementById('manage_flair').checked;
+    const managePost = document.getElementById('manage_post').checked;
+    editMod(userName, subReddit, everything, manageUsers, manageSettings, manageFlair, managePost);
+  };
+
+  const {
+    openEdit, handleClickCloseEdit,
+  } = React.useContext(EditContext);
+  return (
+    <StyledDialog
+      width="538px"
+      height="450px"
+      fullScreen
+      open={openEdit}
+    >
+      <Box>
+        <Header buttonFunction={handleClickCloseEdit} headerText={`Edit u/${userName}`} />
+        <Divider />
+        <Typography
+          color="#1C1C1C"
+          fontSize="16px"
+          fontWeight={600}
+          margin="5px 16px"
+        >
+          Access
+        </Typography>
+      </Box>
+      <Permissions />
+      <FooterContainer>
+        <Foooter
+          firstButtonFunction={handleClickCloseEdit}
+          firstButtonText="Cancel"
+          secondButtonFunction={handleEdit}
+          secondButtonText="Save"
+        />
+      </FooterContainer>
+    </StyledDialog>
+  );
+}
+
+export default EditPopUp;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Moderators_EditPopUp_editServer.js.html b/docs/components_Moderation_ModUserMng_Moderators_EditPopUp_editServer.js.html new file mode 100644 index 00000000..3ffacdd5 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Moderators_EditPopUp_editServer.js.html @@ -0,0 +1,86 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Moderators/EditPopUp/editServer.js + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Moderators/EditPopUp/editServer.js

+ + + + + + +
+
+
// services
+import axios from '../../../../../services/instance';
+
+/**
+*
+* Function to perfom api request and Edit moderator data
+* @param {String} userNmae User name of the user
+* @param {string} subredditName - name of the subreddit
+* @param {boolean} everything - moderator has all access in the subreddit
+* @param {boolean} manageUsers - moderator has access on user only
+* @param {boolean} manageSettings - moderator has access on settings
+* @param {boolean} manageFlair - moderator has access on post flairs
+* @param {boolean} managePost - moderator has access on posts
+* @returns void
+*/
+
+export const editMod = (userName, subReddit, everything, manageUsers, manageSettings, manageFlair, managePost) => {
+  axios.patch(`/subreddits/${subReddit}/moderators/${userName}`, JSON.stringify({
+    permissions: {
+      all: everything,
+      access: manageUsers,
+      config: manageSettings,
+      flair: manageFlair,
+      posts: managePost,
+    },
+  })).then((response) => {
+    console.log(response);
+    if (response.status === 200 || response.status === 201) {
+      console.log('sucess');
+    }
+  }).catch((error) => {
+    console.log(error);
+    console.log(error.response.data.errorMessage);
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Moderators_InvitationPopUp_InvitationPopUp.jsx.html b/docs/components_Moderation_ModUserMng_Moderators_InvitationPopUp_InvitationPopUp.jsx.html new file mode 100644 index 00000000..0b04b859 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Moderators_InvitationPopUp_InvitationPopUp.jsx.html @@ -0,0 +1,119 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Moderators/InvitationPopUp/InvitationPopUp.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Moderators/InvitationPopUp/InvitationPopUp.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import * as React from 'react';
+import { Divider, Box, Typography } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import { StyledDialog, FooterContainer } from '../../styles';
+import { InvitationContext } from '../Moderators';
+import Header from '../../Header/Header';
+import Username from '../../Username/Username';
+import Foooter from '../../Footer/Footer';
+import Permissions from '../Permissions/Persmissions';
+import { inviteMod } from './invitationServer';
+
+/**
+ * invitation popup for moderator page
+ * @component
+ * @return {React.Component} - invite moderator popup component
+ */
+
+function InvitationPopUp() {
+  const { subReddit } = useParams();
+
+  const handleInvite = async () => {
+    const userName = document.getElementById('username').value;
+    const everything = document.getElementById('everything').checked;
+    const manageUsers = document.getElementById('manage_users').checked;
+    const manageSettings = document.getElementById('manage_settings').checked;
+    const manageFlair = document.getElementById('manage_flair').checked;
+    const managePost = document.getElementById('manage_post').checked;
+    inviteMod(userName, subReddit, everything, manageUsers, manageSettings, manageFlair, managePost);
+  };
+
+  const {
+    openInvitation, handleClickCloseInvitation,
+  } = React.useContext(InvitationContext);
+  return (
+    <StyledDialog
+      width="538px"
+      height="520px"
+      fullScreen
+      open={openInvitation}
+    >
+      <Box>
+        <Header buttonFunction={handleClickCloseInvitation} headerText="Invite moderators" />
+        <Divider />
+        <Username placeholder="Enter username" />
+        <Typography
+          color="#1C1C1C"
+          fontSize="16px"
+          fontWeight={600}
+          paddingLeft="16px"
+        >
+          Give them access to...
+        </Typography>
+      </Box>
+      <Permissions />
+      <FooterContainer>
+        <Foooter
+          firstButtonFunction={handleClickCloseInvitation}
+          firstButtonText="Cancel"
+          secondButtonFunction={handleInvite}
+          secondButtonText="Invite"
+        />
+      </FooterContainer>
+    </StyledDialog>
+  );
+}
+
+export default InvitationPopUp;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Moderators_InvitationPopUp_invitationServer.js.html b/docs/components_Moderation_ModUserMng_Moderators_InvitationPopUp_invitationServer.js.html new file mode 100644 index 00000000..26c3d131 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Moderators_InvitationPopUp_invitationServer.js.html @@ -0,0 +1,86 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Moderators/InvitationPopUp/invitationServer.js + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Moderators/InvitationPopUp/invitationServer.js

+ + + + + + +
+
+
// services
+import axios from '../../../../../services/instance';
+
+/**
+*
+* Function to perfom api request. invite a certain user to the subreddit.
+* @param {String} userNmae User name of the user
+* @param {string} subredditName - name of the subreddit
+* @param {boolean} everything - moderator has all access in the subreddit
+* @param {boolean} manageUsers - moderator has access on user only
+* @param {boolean} manageSettings - moderator has access on settings
+* @param {boolean} manageFlair - moderator has access on post flairs
+* @param {boolean} managePost - moderator has access on posts
+* @returns void
+*/
+
+export const inviteMod = (userName, subReddit, everything, manageUsers, manageSettings, manageFlair, managePost) => {
+  axios.post(`/subreddits/${subReddit}/moderators/${userName}`, JSON.stringify({
+    permissions: {
+      all: everything,
+      access: manageUsers,
+      config: manageSettings,
+      flair: manageFlair,
+      posts: managePost,
+    },
+  })).then((response) => {
+    console.log(response);
+    if (response.status === 200 || response.status === 201) {
+      console.log('sucess');
+    }
+  }).catch((error) => {
+    console.log(error);
+    console.log(error.response.data.errorMessage);
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Moderators_LeavePopUp_LeavePopUp.jsx.html b/docs/components_Moderation_ModUserMng_Moderators_LeavePopUp_LeavePopUp.jsx.html new file mode 100644 index 00000000..d798317c --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Moderators_LeavePopUp_LeavePopUp.jsx.html @@ -0,0 +1,97 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Moderators/LeavePopUp/LeavePopUp.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Moderators/LeavePopUp/LeavePopUp.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import * as React from 'react';
+import { Divider, Box, Typography } from '@mui/material';
+import { StyledDialog, FooterContainer } from '../../styles';
+import { LeaveContext } from '../Moderators';
+import Header from '../../Header/Header';
+import Footer from '../../Footer/Footer';
+
+/**
+ * Leave moderator popup for moderator page
+ * @component
+ * @property {boolean} openLeave determine the state of the popup (opened or closed)
+ * @property {function} handleClickCloseLeave close the popup
+ * @return {React.Component} - invite moderator popup component
+ */
+
+function LeavePopUp() {
+  const {
+    openLeave, handleClickCloseLeave,
+  } = React.useContext(LeaveContext);
+  return (
+    <StyledDialog
+      width="538px"
+      height="213px"
+      fullScreen
+      open={openLeave}
+    >
+      <Box>
+        <Header buttonFunction={handleClickCloseLeave} headerText="Leave as mod" />
+        <Divider />
+      </Box>
+      <Box sx={{ padding: '16px' }}>
+        <Typography fontSize="14px">
+          Once you leave as a mod, you will lose mod permissions and will be unable
+          to access any mod tools for this community. Are you sure you wish to leave
+          as a mod of this community?
+        </Typography>
+      </Box>
+      <FooterContainer>
+        <Footer buttonFunction={handleClickCloseLeave} firstButtonText="Cancel" secondButtonText="Leave" />
+      </FooterContainer>
+    </StyledDialog>
+  );
+}
+
+export default LeavePopUp;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Moderators_Moderators.jsx.html b/docs/components_Moderation_ModUserMng_Moderators_Moderators.jsx.html new file mode 100644 index 00000000..01c133a3 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Moderators_Moderators.jsx.html @@ -0,0 +1,136 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Moderators/Moderators.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Moderators/Moderators.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+/* eslint-disable react/jsx-no-constructed-context-values */
+import { Typography } from '@mui/material';
+import ErrorOutlineOutlinedIcon from '@mui/icons-material/ErrorOutlineOutlined';
+import * as React from 'react';
+import { useParams } from 'react-router-dom';
+import {
+  QueueBox, QueueText, ControlBar,
+} from '../styles';
+import { ModMainPage } from '../../ModerationMainPage/styles';
+import LeavePopUp from './LeavePopUp/LeavePopUp';
+import { RedditButton } from '../../styles';
+import Invitation from './InvitationPopUp/InvitationPopUp';
+import ModeratorsList from './NonEmptyModerator/ModeratorsList/ModeratorsList';
+
+export const LeaveContext = React.createContext();
+export const InvitationContext = React.createContext();
+
+/**
+ * moderators whole page
+ * @component
+ * @return {React.Component} - mdoerators page component
+ */
+
+function Moderator() {
+  const { subReddit } = useParams();
+
+  const [openLeave, setOpenLeave] = React.useState(false);
+  const handleClickOpenLeave = () => { setOpenLeave(true); };
+  const handleClickCloseLeave = () => { setOpenLeave(false); };
+
+  const [openInvitation, setOpenInvitation] = React.useState(false);
+  const handleClickOpenInvitation = () => { setOpenInvitation(true); };
+  const handleClickCloseInvitation = () => { setOpenInvitation(false); };
+
+  return (
+    <ModMainPage>
+      <LeaveContext.Provider value={{
+        openLeave, handleClickCloseLeave,
+      }}
+      >
+        <LeavePopUp />
+      </LeaveContext.Provider>
+      <InvitationContext.Provider value={{
+        openInvitation, handleClickCloseInvitation,
+      }}
+      >
+        <Invitation />
+      </InvitationContext.Provider>
+      <ControlBar>
+        <RedditButton
+          fontSize="14px"
+          padding="0px 24px 0px 24px"
+          fontWeight="bold"
+          variant="outlined"
+          sx={{ marginRight: '12px' }}
+          onClick={handleClickOpenLeave}
+        >
+          Leave as mod
+        </RedditButton>
+        <RedditButton
+          fontSize="14px"
+          padding="0px 24px 0px 24px"
+          fontWeight="bold"
+          variant="contained"
+          onClick={handleClickOpenInvitation}
+        >
+          Invite user as mode
+        </RedditButton>
+      </ControlBar>
+      <QueueBox>
+        <QueueText>
+          <Typography variant="h6">
+            Moderators of r/
+            {subReddit}
+          </Typography>
+          <ErrorOutlineOutlinedIcon color="primary" />
+        </QueueText>
+      </QueueBox>
+      <ModeratorsList />
+    </ModMainPage>
+  );
+}
+
+export default Moderator;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Moderators_NonEmptyModerator_ModeratorsList_ModeratorsList.jsx.html b/docs/components_Moderation_ModUserMng_Moderators_NonEmptyModerator_ModeratorsList_ModeratorsList.jsx.html new file mode 100644 index 00000000..4665ad71 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Moderators_NonEmptyModerator_ModeratorsList_ModeratorsList.jsx.html @@ -0,0 +1,160 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Moderators/NonEmptyModerator/ModeratorsList/ModeratorsList.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Moderators/NonEmptyModerator/ModeratorsList/ModeratorsList.jsx

+ + + + + + +
+
+
// import { Moderators } from '../../List';
+import { useParams } from 'react-router-dom';
+import { Typography } from '@mui/material';
+import * as React from 'react';
+import NoResult from '../../../NoResult/NoResult';
+import SearchResultBar from '../../../SearchResultBar/SearchResultBar';
+import SearchBar from '../../../SearchBar/SearchBar';
+import { moderatorsFetch, invitedmoderatorsFetch } from './moderatorsServer';
+import NonEmptyModerator from '../NonEmptyModerator';
+import { ModeratorsTypeContainer } from '../../../styles';
+import calculateTime from '../../../../../../utils/calculateTime';
+
+/**
+ * moderators list
+ * @component
+ * @return {React.Component} - moderators list component
+ */
+
+function ModeratorsList() {
+  const { subReddit } = useParams();
+  const [data, setData] = React.useState('');
+  const childToParent = (childData) => {
+    setData(childData);
+  };
+  const [moderators] = moderatorsFetch(subReddit);
+  const [invitedModerators] = invitedmoderatorsFetch(subReddit);
+  const [filteredData, setfilteredData] = React.useState([]);
+
+  React.useEffect(() => {
+    setfilteredData(moderators?.filter((users) => users.user.userName.toLowerCase().includes(data)));
+  }, [data, moderators]);
+
+  return (
+    <>
+      <SearchBar childToParent={childToParent} />
+      {
+        (filteredData.length !== 0 && data !== '') && (
+        <SearchResultBar
+          resultNumber={filteredData.length}
+          filteredData={filteredData}
+          childToParent={childToParent}
+        />
+        )
+      }
+      {
+        (filteredData.length === 0 && data !== '') && <NoResult query={data} childToParent={childToParent} />
+      }
+      <ModeratorsTypeContainer>
+        {
+      filteredData.map((users, index) => {
+        const {
+          user, moderatorPermissions,
+        } = users;
+        console.log(user);
+        return (
+          <NonEmptyModerator
+            key={`${index + 0}`}
+            userName={user.userName}
+            profilePicture={user.profilePicture}
+            modDate={calculateTime(user.joinDate)}
+            all={moderatorPermissions.all}
+            access={moderatorPermissions.access}
+            config={moderatorPermissions.config}
+            flair={moderatorPermissions.falir}
+            posts={moderatorPermissions.posts}
+            type="0"
+          />
+        );
+      })
+    }
+      </ModeratorsTypeContainer>
+      {(invitedModerators.length !== 0 && filteredData.length === moderators.length) && (
+        <ModeratorsTypeContainer>
+          <Typography
+            fontSize="15px"
+            color="#1C1C1C"
+            fontWeight={600}
+            margin="0px 0px 8px 24px"
+          >
+            Invited moderators
+          </Typography>
+          {
+      invitedModerators.map((users, index) => {
+        const {
+          user, moderatorPermissions,
+        } = users;
+        return (
+          <NonEmptyModerator
+            key={`${index + 0}`}
+            userName={user.userName}
+            profilePicture={user.profilePicture}
+            modDate={calculateTime(user.joinDate)}
+            all={moderatorPermissions.all}
+            access={moderatorPermissions.access}
+            config={moderatorPermissions.config}
+            flair={moderatorPermissions.falir}
+            posts={moderatorPermissions.posts}
+            type="1"
+          />
+        );
+      })
+    }
+        </ModeratorsTypeContainer>
+      )}
+    </>
+  );
+}
+
+export default ModeratorsList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Moderators_NonEmptyModerator_ModeratorsList_moderatorsServer.js.html b/docs/components_Moderation_ModUserMng_Moderators_NonEmptyModerator_ModeratorsList_moderatorsServer.js.html new file mode 100644 index 00000000..a22d7b01 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Moderators_NonEmptyModerator_ModeratorsList_moderatorsServer.js.html @@ -0,0 +1,102 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Moderators/NonEmptyModerator/ModeratorsList/moderatorsServer.js + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Moderators/NonEmptyModerator/ModeratorsList/moderatorsServer.js

+ + + + + + +
+
+
import { useState, useEffect } from 'react';
+import axios from '../../../../../../services/instance';
+
+/**
+*
+* Function to perfom api request. fetch list of moderators
+* @param {string} subredditName - name of the subreddit
+* @returns {Array} array of moderators
+*/
+
+export const moderatorsFetch = (subredditName) => {
+  const [data, setData] = useState([]);
+
+  const api = `/subreddits/${subredditName}/moderators`;
+  useEffect(() => {
+    axios.get(api) // fetch api
+      .then((actualData) => {
+        console.log(actualData.data);
+        setData(actualData.data.data);
+      })
+      .catch((error) => {
+        if (error.response.status === 401) {
+          window.location.href = './login';
+        }
+
+        console.log(error);
+      });
+  }, [api]);
+  return [data];
+};
+
+export const invitedmoderatorsFetch = (subredditName) => {
+  const [data, setData] = useState([]);
+
+  const api = `/subreddits/${subredditName}/invited_moderators`;
+  useEffect(() => {
+    axios.get(api) // fetch api
+      .then((actualData) => {
+        console.log(actualData.data.status);
+        setData(actualData.data.data);
+      })
+      .catch((error) => {
+        if (error.response.status === 401) {
+          window.location.href = './login';
+        }
+
+        console.log(error);
+      });
+  }, [api]);
+  return [data];
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Moderators_NonEmptyModerator_NonEmptyModerator.jsx.html b/docs/components_Moderation_ModUserMng_Moderators_NonEmptyModerator_NonEmptyModerator.jsx.html new file mode 100644 index 00000000..5cbf5b7f --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Moderators_NonEmptyModerator_NonEmptyModerator.jsx.html @@ -0,0 +1,193 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Moderators/NonEmptyModerator/NonEmptyModerator.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Moderators/NonEmptyModerator/NonEmptyModerator.jsx

+ + + + + + +
+
+
/* eslint-disable react/jsx-no-constructed-context-values */
+/* eslint-disable import/no-cycle */
+import {
+  Box, Typography, IconButton,
+} from '@mui/material';
+import EditIcon from '@mui/icons-material/Edit';
+import * as React from 'react';
+import DeleteIcon from '@mui/icons-material/Delete';
+import { useNavigate } from 'react-router-dom';
+import { StyledAvatar, UserBar, UserContainer } from '../../styles';
+import RemovePopUp from '../RemovePopUp/RemovePopUp';
+import EditPopUp from '../EditPopUp/EditPopUp';
+
+export const RemoveContext = React.createContext();
+export const EditContext = React.createContext();
+
+/**
+ * non empty moderator page
+ * @component
+ * @property {string} username the username of the moderator
+ * @property {string} profilePicture it is the link to the profile picture of the moderator
+ * @property {string} modDate it is the date to be a moderator
+ * @property {boolean} all indicates that the moderator has all privileges
+ * @property {boolean} access indicates that tha moderator has the control on user
+ * @property {boolean} confing indicates that the moderator has the control on settings
+ * @property {boolean} flair indicates that the moderator has the control on post flairs
+ * @property {boolean} posts indicates that the moderator has the control on posts
+ * @property {integer} type determine the type of moderators if invited or arleady a moderator
+ * @return {React.Component} - non empty moderator page component
+ */
+
+function NonEmptyModerator(props) {
+  // 0 stands for all moderators (marked as editable but handeled in database)
+  // 1 stands for Invited moderators
+  const {
+    userName, profilePicture, modDate, all, access, config, flair, posts, type,
+  } = props;
+
+  const navigate = useNavigate();
+
+  // navigate
+  const handleClickUser = (userName) => {
+    navigate(`/user/${userName}`);
+  };
+
+  const [openRemove, setOpenRemove] = React.useState(false);
+  const handleClickOpenRemove = () => { setOpenRemove(true); };
+  const handleClickCloseRemove = () => { setOpenRemove(false); };
+
+  const [openEdit, setOpenEdit] = React.useState(false);
+  const handleClickOpenEdit = () => { setOpenEdit(true); };
+  const handleClickCloseEdit = () => { setOpenEdit(false); };
+
+  const handlePermissions = () => {
+    const permissions = [];
+    if (all === true) permissions.push('Everything');
+    else {
+      if (access === true) permissions.push('Manage Users, ');
+      if (config === true) permissions.push('Manage Settings, ');
+      if (flair === true) permissions.push('Manage Flair, ');
+      if (posts === true) permissions.push('Manage Posts & Comments, ');
+      const lastElemnt = permissions.pop().trimEnd();
+      permissions.push(lastElemnt.substring(0, lastElemnt.length - 1));
+    }
+    return permissions;
+  };
+
+  return (
+    <UserBar>
+      <RemoveContext.Provider value={{
+        openRemove, handleClickCloseRemove, userName,
+      }}
+      >
+        <RemovePopUp />
+      </RemoveContext.Provider>
+      <EditContext.Provider value={{
+        openEdit, handleClickCloseEdit,
+      }}
+      >
+        <EditPopUp userName={userName} />
+      </EditContext.Provider>
+      <UserContainer onClick={() => handleClickUser(userName)}>
+        <StyledAvatar src={profilePicture} variant="square" />
+        <Typography
+          padding="8px"
+          fontSize="15px"
+          fontWeight="bold"
+        >
+          {userName}
+        </Typography>
+      </UserContainer>
+      <Box display="flex">
+        <Typography
+          padding="8px"
+          fontSize="12px"
+          color="#878A8C"
+          width="max-content"
+        >
+          {modDate}
+        </Typography>
+      </Box>
+      <Box sx={{
+        alignItems: 'center', display: 'flex', padding: '8px 16px', width: '100%', justifyContent: 'flex-end',
+      }}
+      >
+        {(() => {
+          switch (type) {
+            case '1': return (
+              <>
+                <Typography
+                  padding="4px"
+                  fontSize="12px"
+                  color="#878A8C"
+                >
+                  {handlePermissions()}
+                </Typography>
+                <IconButton disableRipple disableTouchRipple onClick={handleClickOpenRemove}>
+                  <DeleteIcon fontSize="small" />
+                </IconButton>
+              </>
+            );
+            default: return (
+              <>
+                <Typography
+                  padding="4px"
+                  fontSize="12px"
+                  color="#878A8C"
+                >
+                  {handlePermissions()}
+                </Typography>
+                <IconButton disableRipple disableTouchRipple onClick={handleClickOpenEdit}>
+                  <EditIcon fontSize="small" />
+                </IconButton>
+              </>
+            );
+          }
+        })()}
+      </Box>
+    </UserBar>
+  );
+}
+export default NonEmptyModerator;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Moderators_Permissions_Persmissions.jsx.html b/docs/components_Moderation_ModUserMng_Moderators_Permissions_Persmissions.jsx.html new file mode 100644 index 00000000..82526576 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Moderators_Permissions_Persmissions.jsx.html @@ -0,0 +1,177 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Moderators/Permissions/Persmissions.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Moderators/Permissions/Persmissions.jsx

+ + + + + + +
+
+
import * as React from 'react';
+import { Checkbox, Divider } from '@mui/material';
+import { StyledFormHelperText, StyledFormControlLabel, StyledPermissionContainer } from './styled';
+
+/**
+ * permissions that tha moderator has
+ * @component
+ * @return {React.Component} - permissions that the moderator has
+ */
+
+export default function IndeterminateCheckbox() {
+  const [checkedAccess, setChecked1] = React.useState(true);
+  const [checkedConfig, setChecked2] = React.useState(true);
+  const [checkedFlair, setChecked3] = React.useState(true);
+  const [checkedPosts, setChecked4] = React.useState(true);
+
+  const handleChangeAccess = (event) => {
+    setChecked1(event.target.checked);
+  };
+  const handleChangeConfig = (event) => {
+    setChecked2(event.target.checked);
+  };
+  const handleChangeFlairs = (event) => {
+    setChecked3(event.target.checked);
+  };
+  const handleChangePosts = (event) => {
+    setChecked4(event.target.checked);
+  };
+
+  const handleChangeAll = (event) => {
+    handleChangeAccess(event);
+    handleChangeConfig(event);
+    handleChangeFlairs(event);
+    handleChangePosts(event);
+  };
+
+  const children = (
+    <StyledPermissionContainer>
+      <StyledFormControlLabel
+        label="Manage Users"
+        control={(
+          <Checkbox
+            id="manage_users"
+            disableTouchRipple
+            disableRipple
+            size="small"
+            checked={checkedAccess}
+            onChange={handleChangeAccess}
+          />
+)}
+      />
+      <StyledFormHelperText>
+        Access mod notes, ban and mute users, and approve submitters*.
+      </StyledFormHelperText>
+      <StyledFormControlLabel
+        label="Manage Settings"
+        control={(
+          <Checkbox
+            id="manage_settings"
+            disableTouchRipple
+            disableRipple
+            size="small"
+            checked={checkedConfig}
+            onChange={handleChangeConfig}
+          />
+)}
+      />
+      <StyledFormHelperText>
+        Manage community settings, appearance, emojis, rules, and AutoMod*.
+      </StyledFormHelperText>
+      <StyledFormControlLabel
+        label="Manage Flair"
+        control={(
+          <Checkbox
+            id="manage_flair"
+            disableTouchRipple
+            disableRipple
+            size="small"
+            checked={checkedFlair}
+            onChange={handleChangeFlairs}
+          />
+)}
+      />
+      <StyledFormHelperText>
+        Create and manage user and post flair.
+      </StyledFormHelperText>
+      <StyledFormControlLabel
+        label="Manage Posts & Comments"
+        control={(
+          <Checkbox
+            id="manage_post"
+            disableTouchRipple
+            disableRipple
+            size="small"
+            checked={checkedPosts}
+            onChange={handleChangePosts}
+          />
+)}
+      />
+      <StyledFormHelperText>
+        Access queues, take action on content, and manage collections and events.
+      </StyledFormHelperText>
+    </StyledPermissionContainer>
+  );
+
+  return (
+    <>
+      <StyledFormControlLabel
+        label="Everything"
+        control={(
+          <Checkbox
+            id="everything"
+            size="small"
+            checked={checkedAccess && checkedConfig && checkedFlair && checkedPosts}
+            onChange={handleChangeAll}
+          />
+        )}
+      />
+      <StyledFormHelperText>
+        Full access including the ability to manage moderator access and permissions.
+      </StyledFormHelperText>
+      <Divider sx={{ marginTop: '16px' }} />
+      {children}
+    </>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Moderators_RemovePopUp_Delserver.js.html b/docs/components_Moderation_ModUserMng_Moderators_RemovePopUp_Delserver.js.html new file mode 100644 index 00000000..194f9897 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Moderators_RemovePopUp_Delserver.js.html @@ -0,0 +1,72 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Moderators/RemovePopUp/Delserver.js + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Moderators/RemovePopUp/Delserver.js

+ + + + + + +
+
+
// services
+import axios from '../../../../../services/instance';
+
+/**
+*
+* Function to perfom api request. remove invitation
+* @param {String} userNmae User name of the user
+* @param {string} subredditName - name of the subreddit
+* @returns void
+*/
+export const delMod = (userName, subReddit) => {
+  axios.del(`/subreddits/${subReddit}/moderators/${userName}`).then((response) => {
+    console.log(response);
+    if (response.status === 200 || response.status === 201) {
+      console.log('sucess');
+    }
+  }).catch((error) => {
+    console.log(error);
+    console.log(error.response.data.errorMessage);
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Moderators_RemovePopUp_RemovePopUp.jsx.html b/docs/components_Moderation_ModUserMng_Moderators_RemovePopUp_RemovePopUp.jsx.html new file mode 100644 index 00000000..315afca5 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Moderators_RemovePopUp_RemovePopUp.jsx.html @@ -0,0 +1,103 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Moderators/RemovePopUp/RemovePopUp.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Moderators/RemovePopUp/RemovePopUp.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import * as React from 'react';
+import { Divider, Box, Typography } from '@mui/material';
+// import { useParams } from 'react-router-dom';
+import { StyledDialog, FooterContainer } from '../../styles';
+import { RemoveContext } from '../NonEmptyModerator/NonEmptyModerator';
+import Header from '../../Header/Header';
+import Footer from '../../Footer/Footer';
+// import { delMod } from './Delserver';
+
+/**
+ * remove the invitation of the moderator
+ * @component
+ * @return {React.Component} - remove the invitation of the moderator component
+ */
+
+function RemovePopUp() {
+  // const { subReddit } = useParams();
+  const {
+    openRemove, handleClickCloseRemove, userName,
+  } = React.useContext(RemoveContext);
+  // const handleDelMod = () => {
+  //   delMod(userName, subReddit);
+  // };
+  return (
+    <StyledDialog
+      width="fit-content"
+      height="190px"
+      fullScreen
+      open={openRemove}
+    >
+      <Box>
+        <Header buttonFunction={handleClickCloseRemove} headerText="Confirm" />
+        <Divider />
+      </Box>
+      <Box sx={{ padding: '16px' }}>
+        <Typography sx={{ margin: '10px 0px' }}>
+          Are you sure you want to rescind the moderator invite to
+          {' '}
+          {userName}
+          {' '}
+          ?
+        </Typography>
+      </Box>
+      <FooterContainer>
+        <Footer buttonFunction={handleClickCloseRemove} firstButtonText="Cancel" secondButtonText="Remove" />
+      </FooterContainer>
+    </StyledDialog>
+  );
+}
+
+export default RemovePopUp;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Muted_EmptyMuted_EmptyMuted.jsx.html b/docs/components_Moderation_ModUserMng_Muted_EmptyMuted_EmptyMuted.jsx.html new file mode 100644 index 00000000..b9ffd8de --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Muted_EmptyMuted_EmptyMuted.jsx.html @@ -0,0 +1,75 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Muted/EmptyMuted/EmptyMuted.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Muted/EmptyMuted/EmptyMuted.jsx

+ + + + + + +
+
+
import { Typography } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import VolumeOffOutlinedIcon from '@mui/icons-material/VolumeOffOutlined';
+import { EmptyBox } from '../../styles';
+
+/**
+ * empty muted page
+ * @component
+ * @return {React.Component} - empty muted page component
+ */
+
+function EmptyMuted() {
+  const { subReddit } = useParams();
+  return (
+    <EmptyBox>
+      <VolumeOffOutlinedIcon sx={{ color: '#7c7c7c' }} fontSize="large" />
+      <Typography variant="h6" color="#7c7c7c">
+        No muted users in r/
+        {subReddit}
+      </Typography>
+    </EmptyBox>
+  );
+}
+export default EmptyMuted;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Muted_MuteUser.jsx.html b/docs/components_Moderation_ModUserMng_Muted_MuteUser.jsx.html new file mode 100644 index 00000000..6c0797aa --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Muted_MuteUser.jsx.html @@ -0,0 +1,111 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Muted/MuteUser.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Muted/MuteUser.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+/* eslint-disable react/jsx-no-constructed-context-values */
+import { Typography } from '@mui/material';
+import ErrorOutlineOutlinedIcon from '@mui/icons-material/ErrorOutlineOutlined';
+import * as React from 'react';
+import {
+  QueueBox, QueueText, ControlBar,
+} from '../styles';
+import { ModMainPage } from '../../ModerationMainPage/styles';
+import MutePopUp from './MuteUserPopUp/MutePopUp/MutePopUp';
+import { RedditButton } from '../../styles';
+import MutedUserList from './NonEmptyMuted/MutedUserList/MutedUserList';
+
+export const MuteContext = React.createContext();
+
+/**
+ * the whole page of muted
+ * @component
+ * @return {React.Component} - muted user page
+ */
+
+function Mute() {
+  const [openMute, setOpenMute] = React.useState(false);
+
+  const handleClickOpenMute = () => { setOpenMute(true); };
+  const handleClickCloseMute = () => { setOpenMute(false); };
+  React.useEffect(() => () => {
+
+  }, []);
+  return (
+    <ModMainPage>
+      <MuteContext.Provider value={{
+        openMute, handleClickCloseMute,
+      }}
+      >
+        <MutePopUp />
+      </MuteContext.Provider>
+      <ControlBar>
+        <RedditButton
+          fontSize="14px"
+          padding="0px 24px 0px 24px"
+          fontWeight="bold"
+          variant="contained"
+          onClick={handleClickOpenMute}
+        >
+          Mute user
+        </RedditButton>
+      </ControlBar>
+      <QueueBox>
+        <QueueText>
+          <Typography variant="h6">Muted users</Typography>
+          <ErrorOutlineOutlinedIcon color="primary" />
+        </QueueText>
+      </QueueBox>
+      <MutedUserList />
+    </ModMainPage>
+  );
+}
+
+export default Mute;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Muted_MuteUserPopUp_MuteMessage_MuteMessage.jsx.html b/docs/components_Moderation_ModUserMng_Muted_MuteUserPopUp_MuteMessage_MuteMessage.jsx.html new file mode 100644 index 00000000..6b537ee0 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Muted_MuteUserPopUp_MuteMessage_MuteMessage.jsx.html @@ -0,0 +1,90 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Muted/MuteUserPopUp/MuteMessage/MuteMessage.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Muted/MuteUserPopUp/MuteMessage/MuteMessage.jsx

+ + + + + + +
+
+
import * as React from 'react';
+import { StyledBox } from './styles';
+import { FullDiscTextArea, Count } from '../../../../Rules/AddRule/style';
+
+/**
+ * mute message
+ * @component
+ * @return {React.Component} - mute message component (text area)
+ */
+
+function MuteMessage() {
+  const [count, setCount] = React.useState(300);
+  const check = (e) => {
+    const ele = e?.target?.value;
+    if (500 - ele.length >= 0) { setCount(500 - ele.length); }
+  };
+  return (
+    <StyledBox>
+      <FullDiscTextArea
+        placeholder="Reason they were muted"
+        id="mute_message"
+        onChange={check}
+        onInput={(e) => {
+          // eslint-disable-next-line radix
+          e.target.value = e.target.value.slice(0, 500);
+        }}
+      />
+      <Count
+        condition={(count === 0).toString()}
+      >
+        {count}
+        {' '}
+        Characters remaining
+      </Count>
+    </StyledBox>
+  );
+}
+
+export default MuteMessage;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Muted_MuteUserPopUp_MutePopUp_MutePopUp.jsx.html b/docs/components_Moderation_ModUserMng_Muted_MuteUserPopUp_MutePopUp_MutePopUp.jsx.html new file mode 100644 index 00000000..3bacb0f4 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Muted_MuteUserPopUp_MutePopUp_MutePopUp.jsx.html @@ -0,0 +1,109 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Muted/MuteUserPopUp/MutePopUp/MutePopUp.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Muted/MuteUserPopUp/MutePopUp/MutePopUp.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import * as React from 'react';
+import { Divider, Box, Typography } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import { StyledDialog, FooterContainer } from '../../../styles';
+import { MuteContext } from '../../MuteUser';
+import Username from '../../../Username/Username';
+import MuteMessage from '../MuteMessage/MuteMessage';
+import Header from '../../../Header/Header';
+import Footer from '../../../Footer/Footer';
+import { MuteUnmuteUser } from '../MuteServer';
+
+/**
+ * mute popup
+ * @component
+ * @return {React.Component} - mute popup component
+ */
+
+function MutePopUp() {
+  const { subReddit } = useParams();
+
+  const handleClickMute = async () => {
+    const userName = document.getElementById('username').value;
+    const muteNote = document.getElementById('mute_message').value;
+    MuteUnmuteUser(userName, muteNote, subReddit, 'mute');
+  };
+
+  const {
+    openMute, handleClickCloseMute,
+  } = React.useContext(MuteContext);
+  return (
+    <StyledDialog
+      fullScreen
+      open={openMute}
+      width="410px"
+      height="370px"
+    >
+      <Box>
+        <Header buttonFunction={handleClickCloseMute} headerText="Mute user" />
+        <Divider />
+        <Username placeholder="Username to mute" />
+        <Typography fontSize="14px" fontWeight={400} color="#1C1C1C" paddingLeft="16px">Note about why they are muted</Typography>
+        <Typography fontSize="12px" fontWeight={400} color="#878A8C" paddingLeft="16px">Only visible to other moderators. Not visible to user</Typography>
+      </Box>
+      <MuteMessage />
+      <FooterContainer>
+        <Footer
+          firstButtonFunction={handleClickCloseMute}
+          firstButtonText="Cancel"
+          secondButtonFunction={handleClickMute}
+          secondButtonText="Mute user"
+        />
+      </FooterContainer>
+    </StyledDialog>
+  );
+}
+
+export default MutePopUp;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Muted_MuteUserPopUp_MuteServer.js.html b/docs/components_Moderation_ModUserMng_Muted_MuteUserPopUp_MuteServer.js.html new file mode 100644 index 00000000..3962e2e7 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Muted_MuteUserPopUp_MuteServer.js.html @@ -0,0 +1,76 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Muted/MuteUserPopUp/MuteServer.js + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Muted/MuteUserPopUp/MuteServer.js

+ + + + + + +
+
+
// services
+import axios from '../../../../../services/instance';
+
+/**
+*
+* Function to perfom api request. mute or unmute a user
+* @param {String} userNmae User name of the user
+* @param {enum} action  enum mute or unmute
+* @param {string} subredditName - name of the subreddit
+* @param {string} userNote - note from the moderator about this user
+* @returns void
+*/
+export const MuteUnmuteUser = (userName, userNote, subReddit, action) => {
+  axios.post(`/subreddits/${subReddit}/mute_settings/${action}/${userName}`, JSON.stringify({
+    muteMessage: userNote,
+  })).then((response) => {
+    console.log(response);
+    if (response.status === 200 || response.status === 201) {
+      console.log('sucess');
+    }
+  }).catch((error) => {
+    console.log(error);
+    console.log(error.response.data.errorMessage);
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Muted_MuteUserPopUp_UnmutePopUp_UnmutePopUp.jsx.html b/docs/components_Moderation_ModUserMng_Muted_MuteUserPopUp_UnmutePopUp_UnmutePopUp.jsx.html new file mode 100644 index 00000000..6bd9226c --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Muted_MuteUserPopUp_UnmutePopUp_UnmutePopUp.jsx.html @@ -0,0 +1,105 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Muted/MuteUserPopUp/UnmutePopUp/UnmutePopUp.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Muted/MuteUserPopUp/UnmutePopUp/UnmutePopUp.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import * as React from 'react';
+import { Divider, Box, Typography } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import { StyledDialog, FooterContainer } from '../../../styles';
+import { UnmuteContext } from '../../NonEmptyMuted/MutedUser/MutedUser';
+import Header from '../../../Header/Header';
+import Footer from '../../../Footer/Footer';
+import { MuteUnmuteUser } from '../MuteServer';
+
+/**
+ * Unmute Popup
+ * @component
+ * @property  {string} username the username of the muted user
+ * @return {React.Component} - unmute popup component
+ */
+
+function UnmutePopUp(props) {
+  const { subReddit } = useParams();
+  const { userName } = props;
+  const handleUnmute = () => {
+    MuteUnmuteUser(userName, '', subReddit, 'unmute');
+  };
+
+  const {
+    openUnmute, handleClickCloseUnmute,
+  } = React.useContext(UnmuteContext);
+  return (
+    <StyledDialog
+      fullScreen
+      open={openUnmute}
+      width="410px"
+      height="190px"
+    >
+      <Box>
+        <Header buttonFunction={handleClickCloseUnmute} headerText="Confirm" />
+        <Divider />
+      </Box>
+      <Box sx={{ padding: '16px' }}>
+        <Typography fontSize="14px" sx={{ margin: '10px 0px' }}>
+          Are you sure you want to unmute
+          {' '}
+          {userName}
+          ?
+        </Typography>
+      </Box>
+      <FooterContainer>
+        <Footer firstButtonFunction={handleClickCloseUnmute} firstButtonText="Cancel" secondButtonFunction={handleUnmute} secondButtonText="Unmute" />
+      </FooterContainer>
+    </StyledDialog>
+  );
+}
+
+export default UnmutePopUp;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Muted_NonEmptyMuted_MoreDetails_MoreDetails.jsx.html b/docs/components_Moderation_ModUserMng_Muted_NonEmptyMuted_MoreDetails_MoreDetails.jsx.html new file mode 100644 index 00000000..1f66f5ee --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Muted_NonEmptyMuted_MoreDetails_MoreDetails.jsx.html @@ -0,0 +1,111 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Muted/NonEmptyMuted/MoreDetails/MoreDetails.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Muted/NonEmptyMuted/MoreDetails/MoreDetails.jsx

+ + + + + + +
+
+
import { Box, Typography } from '@mui/material';
+import { StyledDetails } from '../../../styles';
+
+/**
+ * more datails tab
+ * @component
+ * @property  {boolean} isOpened determine the state of more details tab to be showed or hidden
+ * @property {string} modNote note from the moderator about the muted user
+ * @return {React.Component} - more details tab
+ */
+
+function MoreDetails(props) {
+  const { modNote, isOpened } = props;
+  return (
+    <StyledDetails
+      display={(isOpened) ? 'flex' : 'none'}
+    >
+      <Box padding="16px" display="flex" alignItems="center" paddingBottom="10px">
+        {(() => {
+          if (modNote === '') {
+            return (
+              <Typography
+                fontSize="10px"
+                color="#878A8C"
+                fontWeight={700}
+                marginRight="3px"
+                textTransform="uppercase"
+              >
+                No mod Note.
+              </Typography>
+            );
+          }
+          return (
+            <>
+              <Typography
+                fontSize="10px"
+                color="#878A8C"
+                fontWeight={700}
+                marginRight="3px"
+                textTransform="uppercase"
+              >
+                mod note:
+              </Typography>
+              <Typography
+                fontSize="12px"
+                color="#1C1C1C"
+                paddingBottom="2px"
+              >
+                {modNote}
+              </Typography>
+            </>
+          );
+        })()}
+
+      </Box>
+    </StyledDetails>
+  );
+}
+
+export default MoreDetails;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Muted_NonEmptyMuted_MutedUserList_MutedServer.js.html b/docs/components_Moderation_ModUserMng_Muted_NonEmptyMuted_MutedUserList_MutedServer.js.html new file mode 100644 index 00000000..3acb5cec --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Muted_NonEmptyMuted_MutedUserList_MutedServer.js.html @@ -0,0 +1,80 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Muted/NonEmptyMuted/MutedUserList/MutedServer.js + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Muted/NonEmptyMuted/MutedUserList/MutedServer.js

+ + + + + + +
+
+
import { useState, useEffect } from 'react';
+import axios from '../../../../../../services/instance';
+
+/**
+*
+* Function to perfom api request. fetch list of muted users
+* @param {string} subredditName - name of the subreddit
+* @returns {Array} array of muted users
+*/
+export const mutedFetch = (subredditName) => {
+  const [data, setData] = useState([]);
+
+  const api = `/subreddits/${subredditName}/muted`;
+  useEffect(() => {
+    axios.get(api) // fetch api
+      .then((actualData) => {
+        console.log(actualData.data.status);
+        setData(actualData.data.data.filter((users) => users.type.includes('muted')));
+      })
+      .catch((error) => {
+        if (error.response.status === 401) {
+          window.location.href = './login';
+        }
+
+        console.log(error);
+      });
+  }, [api]);
+  return [data];
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Muted_NonEmptyMuted_MutedUserList_MutedUserList.jsx.html b/docs/components_Moderation_ModUserMng_Muted_NonEmptyMuted_MutedUserList_MutedUserList.jsx.html new file mode 100644 index 00000000..bd4bdc37 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Muted_NonEmptyMuted_MutedUserList_MutedUserList.jsx.html @@ -0,0 +1,115 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Muted/NonEmptyMuted/MutedUserList/MutedUserList.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Muted/NonEmptyMuted/MutedUserList/MutedUserList.jsx

+ + + + + + +
+
+
import React from 'react';
+import { useParams } from 'react-router-dom';
+import { mutedFetch } from './MutedServer';
+import MutedUser from '../MutedUser/MutedUser';
+import SearchBar from '../../../SearchBar/SearchBar';
+import SearchResultBar from '../../../SearchResultBar/SearchResultBar';
+import NoResult from '../../../NoResult/NoResult';
+import EmptyMuted from '../../EmptyMuted/EmptyMuted';
+
+/**
+ * muted user list
+ * @component
+ * @return {React.Component} - muted user list
+ */
+
+function MutedUserList() {
+  const [data, setData] = React.useState('');
+  const childToParent = (childData) => {
+    setData(childData);
+  };
+  const { subReddit } = useParams();
+  const [MutedUsers] = mutedFetch(subReddit);
+  const [filteredData, setfilteredData] = React.useState([]);
+  React.useEffect(() => {
+    setfilteredData(MutedUsers?.filter((users) => users.user.userName.toLowerCase().includes(data)));
+  }, [data, MutedUsers]);
+
+  return (
+    (MutedUsers.length === 0) ? (<EmptyMuted />) : (
+      <>
+        <SearchBar childToParent={childToParent} />
+        {
+        (filteredData.length !== 0 && data !== '') && (
+        <SearchResultBar
+          resultNumber={filteredData.length}
+          filteredData={filteredData}
+          childToParent={childToParent}
+        />
+        )
+      }
+        {
+       (filteredData.length === 0 && data !== '') && <NoResult query={data} childToParent={childToParent} />
+      }
+        {
+        filteredData.map((users, index) => {
+          const {
+            user, muteInfo,
+          } = users;
+          console.log(muteInfo);
+          return (
+            <MutedUser
+              key={`${index + 0}`}
+              user={user}
+              muteInfo={muteInfo}
+            />
+          );
+        })
+      }
+      </>
+    )
+  );
+}
+
+export default MutedUserList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Muted_NonEmptyMuted_MutedUser_MutedUser.jsx.html b/docs/components_Moderation_ModUserMng_Muted_NonEmptyMuted_MutedUser_MutedUser.jsx.html new file mode 100644 index 00000000..574e8a2c --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Muted_NonEmptyMuted_MutedUser_MutedUser.jsx.html @@ -0,0 +1,146 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Muted/NonEmptyMuted/MutedUser/MutedUser.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Muted/NonEmptyMuted/MutedUser/MutedUser.jsx

+ + + + + + +
+
+
/* eslint-disable react/jsx-no-constructed-context-values */
+/* eslint-disable import/no-cycle */
+import { Box, Typography } from '@mui/material';
+import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
+import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
+import * as React from 'react';
+import { useNavigate } from 'react-router-dom';
+import {
+  UserBar, UserContainer, UserMngButton, StyledAvatar, UsermngButtonContainer, TextContainer,
+} from '../../../styles';
+import MoreDetails from '../MoreDetails/MoreDetails';
+import UnmutePopUp from '../../MuteUserPopUp/UnmutePopUp/UnmutePopUp';
+import calculateTime from '../../../../../../utils/calculateTime';
+
+export const UnmuteContext = React.createContext();
+
+/**
+ * Banned user instace
+ * @component
+ * @property  {object} user an object containing all information about the user from its username until the link to the its profile picture and the date that user is muted
+ * @property {object} muteInfo contain the comment of the moderator on the muted user
+ * @return {React.Component} - Banned user instace component
+ */
+
+function MutedUser(props) {
+  const navigate = useNavigate();
+
+  // navigate
+  const handleClickUser = (userName) => {
+    navigate(`/user/${userName}`);
+  };
+  const { user, muteInfo } = props;
+
+  const [openUnmute, setOpenUnmute] = React.useState(false);
+
+  const handleClickOpenUnmute = () => { setOpenUnmute(true); };
+  const handleClickCloseUnmute = () => { setOpenUnmute(false); };
+
+  const [isOpened, setOpen] = React.useState(false);
+  const handleClick = () => {
+    setOpen(!isOpened);
+  };
+  return (
+    <>
+      <UserBar>
+        <UnmuteContext.Provider value={{
+          openUnmute, handleClickCloseUnmute,
+        }}
+        >
+          <UnmutePopUp userName={user.userName} />
+        </UnmuteContext.Provider>
+        <UserContainer onClick={() => handleClickUser(user.userName)}>
+          <StyledAvatar src={user.profilePicture} variant="square" sx={{ width: '32px', height: '32px' }} />
+          <Box>
+            <Typography
+              padding="8px"
+              fontSize="15px"
+              fontWeight="bold"
+            >
+              {user.userName}
+            </Typography>
+          </Box>
+        </UserContainer>
+        <TextContainer>
+          <Typography
+            padding="8px"
+            fontSize="12px"
+            color="#878A8C"
+          >
+            {calculateTime(user.joinDate)}
+          </Typography>
+        </TextContainer>
+        <UsermngButtonContainer>
+          <UserMngButton
+            disableRipple
+            disableFocusRipple
+            onClick={handleClickOpenUnmute}
+          >
+            Unmute
+          </UserMngButton>
+          <UserMngButton
+            disableRipple
+            disableFocusRipple
+            onClick={handleClick}
+            endIcon={(isOpened) ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
+          >
+            More Details
+          </UserMngButton>
+        </UsermngButtonContainer>
+      </UserBar>
+      <MoreDetails modNote={muteInfo.muteMessage} isOpened={isOpened} />
+    </>
+  );
+}
+export default MutedUser;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_NoResult_NoResult.jsx.html b/docs/components_Moderation_ModUserMng_NoResult_NoResult.jsx.html new file mode 100644 index 00000000..9f72a887 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_NoResult_NoResult.jsx.html @@ -0,0 +1,86 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/NoResult/NoResult.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/NoResult/NoResult.jsx

+ + + + + + +
+
+
import { Typography } from '@mui/material';
+import SearchIcon from '@mui/icons-material/Search';
+import { NoResultBox } from './styles';
+import { UserMngButton } from '../styles';
+
+/**
+ * the whole page of no result that appears when try to seach on a user in user managment section in moderatio page
+ * @component
+ * @property {string} query it is the query in the search input field
+ * @property {function} childToParent it is a function state to pass the query from the child (search bar) to its parent (user management list)
+ * @return {React.Component} - no result page
+ */
+
+function NoResult(props) {
+  const { query, childToParent } = props;
+  return (
+    <NoResultBox>
+      <SearchIcon fontSize="large" />
+      <Typography
+        color="#878A8C"
+        fontSize="18px"
+        padding="30px 0px 0px 0px"
+      >
+        No results for u/
+        {' '}
+        {query}
+      </Typography>
+      <UserMngButton onClick={() => childToParent('')}>
+        See all
+      </UserMngButton>
+    </NoResultBox>
+  );
+}
+
+export default NoResult;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_SearchBar_SearchBar.jsx.html b/docs/components_Moderation_ModUserMng_SearchBar_SearchBar.jsx.html new file mode 100644 index 00000000..abba8be7 --- /dev/null +++ b/docs/components_Moderation_ModUserMng_SearchBar_SearchBar.jsx.html @@ -0,0 +1,81 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/SearchBar/SearchBar.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/SearchBar/SearchBar.jsx

+ + + + + + +
+
+
import SearchIcon from '@mui/icons-material/Search';
+import React from 'react';
+import {
+  StyledInputBase, StyledIconWrapper, StyledSearchBar, StyledSearchContainer,
+} from './styles';
+
+/**
+ * the search bar
+ * @component
+ * @property {function} childToParent it is a function state to pass the query from the child (search bar) to its parent (user management list)
+ * @return {React.Component} - the search bar component
+ */
+
+function SearchBar({ childToParent }) {
+  const [query, serQuery] = React.useState('');
+  return (
+    <StyledSearchBar>
+      <StyledSearchContainer>
+        <StyledInputBase
+          onChange={(e) => serQuery(e.target.value)}
+          placeholder="Search for a user"
+        />
+        <StyledIconWrapper onClick={() => childToParent(query)}>
+          <SearchIcon sx={{ color: 'white', cursor: 'pointer' }} />
+        </StyledIconWrapper>
+      </StyledSearchContainer>
+    </StyledSearchBar>
+  );
+}
+export default SearchBar;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_SearchResultBar_SearchResultBar.jsx.html b/docs/components_Moderation_ModUserMng_SearchResultBar_SearchResultBar.jsx.html new file mode 100644 index 00000000..d906c0bd --- /dev/null +++ b/docs/components_Moderation_ModUserMng_SearchResultBar_SearchResultBar.jsx.html @@ -0,0 +1,108 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/SearchResultBar/SearchResultBar.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/SearchResultBar/SearchResultBar.jsx

+ + + + + + +
+
+
// import React from 'react';
+import { Typography, Box } from '@mui/material';
+import { StyledSearchResultBar } from './styles';
+import { UserMngButton } from '../styles';
+
+/**
+ * the whole page of no result that appears when try to seach on a user in user managment section in moderatio page
+ * @component
+ * @property {string} resultNumber the number of results from the query after search
+ * @property {object} filteredData the result data after searching
+ * @property {function} childToParent a function to pass result data from child to parent
+ * @return {React.Component} - no result page
+ */
+
+function SearchResultBar(props) {
+  const {
+    resultNumber, filteredData, childToParent,
+  } = props;
+  return (
+    <StyledSearchResultBar>
+      <Box display="flex">
+        <Typography
+          fontSize="14px"
+          fontWeight={600}
+          color="#1C1C1C"
+          paddingLeft="15px"
+        >
+          {resultNumber}
+          {' '}
+          search result for&nbsp;
+        </Typography>
+        <Box display="flex">
+          {
+              filteredData.map((users) => {
+                const { user } = users;
+                return (
+                  <Typography
+                    color="#0079D3"
+                    fontSize="14px"
+                    fontWeight={500}
+                  >
+                    {`'${user.userName}'`}
+                    &nbsp;
+                  </Typography>
+                );
+              })
+      }
+        </Box>
+      </Box>
+      <UserMngButton onClick={() => childToParent('')}>
+        See all
+      </UserMngButton>
+    </StyledSearchResultBar>
+  );
+}
+
+export default SearchResultBar;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_ModUserMng_Username_Username.jsx.html b/docs/components_Moderation_ModUserMng_Username_Username.jsx.html new file mode 100644 index 00000000..ed67b9ba --- /dev/null +++ b/docs/components_Moderation_ModUserMng_Username_Username.jsx.html @@ -0,0 +1,76 @@ + + + + + JSDoc: Source: components/Moderation/ModUserMng/Username/Username.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/ModUserMng/Username/Username.jsx

+ + + + + + +
+
+
import { TextField } from '@mui/material';
+import { StyledBox } from './styles';
+
+/**
+ * username input field for all user management serction popups
+ * @component
+ * @property {string} placeholder determine the string that appear in the user input field
+ * @return {React.Component} - username input field component
+ */
+
+function Username(props) {
+  const { placeholder } = props;
+  return (
+    <StyledBox>
+      <TextField
+        id="username"
+        placeholder={placeholder}
+        size="small"
+        fullWidth
+      />
+    </StyledBox>
+  );
+}
+
+export default Username;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Post Flair_Entity_DeleteFlairServer.js.html b/docs/components_Moderation_Post Flair_Entity_DeleteFlairServer.js.html new file mode 100644 index 00000000..7f96295c --- /dev/null +++ b/docs/components_Moderation_Post Flair_Entity_DeleteFlairServer.js.html @@ -0,0 +1,73 @@ + + + + + JSDoc: Source: components/Moderation/Post Flair/Entity/DeleteFlairServer.js + + + + + + + + + + +
+ +

Source: components/Moderation/Post Flair/Entity/DeleteFlairServer.js

+ + + + + + +
+
+
import axios from '../../../../services/instance';
+/**
+ * Delete Flair
+ *
+ * @property {string} Name - name of subreddit
+ * @property {integer} id - id of flair
+ *
+ */
+const DeleteFlair = async (Name, id) => {
+  let statusCode = '';
+  await axios.delete(`subreddits/${Name}/flair/${id}`)
+    .then((response) => {
+      statusCode = response.status;
+    }).catch((error) => {
+      statusCode = error.response.status;
+      console.log(error);
+    });
+  if (statusCode === 401) {
+    window.location.pathname = 'login';
+  }
+};
+export default DeleteFlair;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Post Flair_Entity_EditFlair_Edit.jsx.html b/docs/components_Moderation_Post Flair_Entity_EditFlair_Edit.jsx.html new file mode 100644 index 00000000..b221ed85 --- /dev/null +++ b/docs/components_Moderation_Post Flair_Entity_EditFlair_Edit.jsx.html @@ -0,0 +1,181 @@ + + + + + JSDoc: Source: components/Moderation/Post Flair/Entity/EditFlair/Edit.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/Post Flair/Entity/EditFlair/Edit.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+import { useParams } from 'react-router-dom';
+import Done from '../../../../AlertMessage';
+import EditFlair from './EditFlair';
+import {
+  AddFlair,
+  Cancel,
+  Color,
+  ColorData,
+  Container, Count, FieldData, FormCont, Input, Lable, Save, SecondLable,
+} from './style';
+
+/**
+ * Edit Entity of Flair
+ * @component
+ * @property  {function} check copy id
+ * @property  {function} notEmpty check if input feild is empty or not
+ * @property  {function} SendData send data to backend
+ * @property  {function} EditFlair send edited data to backend
+ *
+ * @return {React.Component} - Edit Entity of Flair
+ */
+
+export default function Edit(props) {
+  const { flair, save, cancel } = props;
+  const [count, setCount] = useState(64 - flair.text.length);
+  const [error, setError] = useState('');
+  const { subReddit } = useParams();
+
+  const check = (e) => {
+    const ele = e?.target?.value;
+    setCount(64 - ele.length);
+  };
+  const notEmpty = (e) => {
+    const ele = e?.target?.value;
+    if (ele.length === 0) {
+      setError('Error: text or emoji is required');
+    } else {
+      setError('');
+    }
+  };
+  const SendData = () => {
+    const text = document.getElementById('text').value;
+    const backgroundColor = document.getElementById('bgColor').value;
+    // const cssClass = document.getElementById('css');
+    const textColor = document.getElementById('textColor').value;
+    console.log(text, backgroundColor, textColor);
+
+    EditFlair(subReddit, flair?._id, {
+      text,
+      backgroundColor,
+      textColor,
+    });
+    save();
+    Done('Chndes Save');
+  };
+  return (
+    <>
+      <Container>
+        <Lable>FLAIR APPEARANCE</Lable>
+        <FieldData>
+          <SecondLable>Flair text</SecondLable>
+          <FormCont>
+            <Input
+              id="text"
+              onChange={check}
+              defaultValue={flair?.text}
+              onInput={(e) => {
+              // eslint-disable-next-line radix
+                e.target.value = e.target.value.slice(0, 21);
+              }}
+              onBlur={notEmpty}
+            />
+          </FormCont>
+          {(error.length === 0)
+            ? (
+              <Count
+                condition={(count === 0).toString()}
+              >
+                {count}
+                {' '}
+                Characters remaining
+              </Count>
+            )
+            : <Count condition="true">{error}</Count>}
+        </FieldData>
+
+        <FieldData>
+          <SecondLable>CSS Class</SecondLable>
+          <FormCont>
+            <Input
+              id="css"
+              onChange={check}
+              defaultValue={flair?.cssClass}
+              placeholder="none"
+            />
+          </FormCont>
+          <Count>
+            Optional
+          </Count>
+        </FieldData>
+
+        <ColorData>
+          <SecondLable>Flair background color</SecondLable>
+          <Color
+            type="color"
+            id="bgColor"
+            defaultValue={flair?.backgroundColor}
+          />
+        </ColorData>
+
+        <ColorData>
+          <SecondLable>Flair text color</SecondLable>
+          <Color
+            type="color"
+            id="textColor"
+            defaultValue={flair?.textColor}
+            placeholder="Aa"
+          />
+        </ColorData>
+      </Container>
+      <AddFlair>
+        <Save onClick={SendData}>
+          Save
+        </Save>
+        <Cancel onClick={cancel}>Cancel</Cancel>
+      </AddFlair>
+    </>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Post Flair_Entity_EditFlair_EditFlair.js.html b/docs/components_Moderation_Post Flair_Entity_EditFlair_EditFlair.js.html new file mode 100644 index 00000000..8fb0afa0 --- /dev/null +++ b/docs/components_Moderation_Post Flair_Entity_EditFlair_EditFlair.js.html @@ -0,0 +1,73 @@ + + + + + JSDoc: Source: components/Moderation/Post Flair/Entity/EditFlair/EditFlair.js + + + + + + + + + + +
+ +

Source: components/Moderation/Post Flair/Entity/EditFlair/EditFlair.js

+ + + + + + +
+
+
import axios from '../../../../../services/instance';
+/**
+ * Edit Flair
+ *
+ * @property {string} Name - name of subreddit
+ * @property {integer} id - id of flair
+ * @property {object} prefs - data to change
+
+ */
+const EditFlair = async (Name, id, prefs) => {
+  let statusCode = '';
+  await axios.patch(`subreddits/${Name}/flair/${id}`, prefs).then((response) => {
+    statusCode = response.status;
+  }).catch((error) => {
+    statusCode = error.response.status;
+    console.log(error);
+  });
+  if (statusCode === 401) {
+    window.location.pathname = 'login';
+  }
+};
+export default EditFlair;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Post Flair_Entity_Entity.jsx.html b/docs/components_Moderation_Post Flair_Entity_Entity.jsx.html new file mode 100644 index 00000000..7b45f8d5 --- /dev/null +++ b/docs/components_Moderation_Post Flair_Entity_Entity.jsx.html @@ -0,0 +1,137 @@ + + + + + JSDoc: Source: components/Moderation/Post Flair/Entity/Entity.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/Post Flair/Entity/Entity.jsx

+ + + + + + +
+
+
import { IconButton, TableCell } from '@mui/material';
+import TableRow from '@mui/material/TableRow';
+import DeleteIcon from '@mui/icons-material/Delete';
+import { useState } from 'react';
+import { useParams } from 'react-router-dom';
+import {
+  Actions, BodyCell, BodyFirstCell, BodyLastCell, Filter, Text,
+} from './style';
+import Edit from './EditFlair/Edit';
+import DeleteFlair from './DeleteFlairServer';
+
+/**
+ * Entity of Flair
+ * @component
+ * @property  {function} copied copy id
+ * @property  {function} Edited show enable form
+ * @property  {function} save clase form and enable add
+ * @property  {function} cancel clase form and enable add
+ *
+ * @return {React.Component} - Entity of Flair
+ */
+
+function Entity(props) {
+  const {
+    row, handleClick, can, trueCan,
+  } = props;
+  const [show, setShow] = useState(false);
+  const { subReddit } = useParams();
+
+  function copied() {
+    alert('text copied');
+  }
+  const Edited = () => {
+    console.log('clicked');
+    handleClick();
+    setShow(true);
+  };
+  const save = () => {
+    trueCan();
+    setShow(false);
+  };
+  const cancel = () => {
+    trueCan();
+    setShow(false);
+  };
+  return (
+    <>
+      <TableRow
+        key={row?.name}
+        sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
+      >
+        <BodyFirstCell>
+          <Text color={row?.textColor} backgroundColor={row?.backgroundColor}>
+            {row?.text}
+          </Text>
+        </BodyFirstCell>
+        <BodyCell align="center" />
+        <BodyCell align="center" />
+        <BodyLastCell align="center">
+          <Actions>
+            <Filter
+              onClick={() => { navigator.clipboard.writeText(row?._id); copied(); }}
+            >
+              Copy ID
+            </Filter>
+            {(can)
+              ? <Filter onClick={() => Edited()}>edit</Filter>
+              : <Filter disabled condition={!can}>edit</Filter>}
+            <IconButton onClick={() => { DeleteFlair(subReddit, row._id); }}>
+              <DeleteIcon />
+            </IconButton>
+          </Actions>
+        </BodyLastCell>
+      </TableRow>
+      {show
+      && (
+      <TableRow>
+        <TableCell align="left" colSpan={4}>
+          <Edit flair={row} save={save} cancel={cancel} />
+        </TableCell>
+      </TableRow>
+      )}
+    </>
+  );
+}
+export default Entity;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Post Flair_NewFlair_NewFlair.jsx.html b/docs/components_Moderation_Post Flair_NewFlair_NewFlair.jsx.html new file mode 100644 index 00000000..78bfc691 --- /dev/null +++ b/docs/components_Moderation_Post Flair_NewFlair_NewFlair.jsx.html @@ -0,0 +1,174 @@ + + + + + JSDoc: Source: components/Moderation/Post Flair/NewFlair/NewFlair.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/Post Flair/NewFlair/NewFlair.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+import { useParams } from 'react-router-dom';
+import Done from '../../../AlertMessage';
+import PostFlair from './PostFlair';
+import {
+  AddFlair, Cancel, Color, ColorData,
+  Container, Count, FieldData, FormCont, Input, Lable, Save, SecondLable, SplitArea,
+} from './style';
+
+/**
+ * New Flair
+ * @component
+ * @property  {function} notEmpty check if the input feild is empty or not
+ * @property  {function} SendData send data to backend
+ *
+ * @return {React.Component} - New Flair
+ */
+
+export default function NewFlair(props) {
+  const { save, cancel } = props;
+  const { subReddit } = useParams();
+
+  const [count, setCount] = useState(64);
+  const [error, setError] = useState('');
+  const check = (e) => {
+    const ele = e?.target?.value;
+    setCount(64 - ele.length);
+  };
+  const notEmpty = (e) => {
+    const ele = e?.target?.value;
+    if (ele.length === 0) {
+      setError('Error: text or emoji is required');
+    } else {
+      setError('');
+    }
+  };
+
+  const SendData = () => {
+    const text = document.getElementById('text').value;
+    const backgroundColor = document.getElementById('bgColor').value;
+    // const cssClass = document.getElementById('css');
+    const textColor = document.getElementById('textColor').value;
+    console.log(text, backgroundColor, textColor);
+    PostFlair(`subreddits/${subReddit}/flair`, text, backgroundColor, textColor);
+    save();
+    Done('Flair Added');
+  };
+  return (
+    <>
+      <Container>
+        <Lable>FLAIR APPEARANCE</Lable>
+        <FieldData>
+          <SecondLable>Flair text</SecondLable>
+          <FormCont>
+            <Input
+              id="text"
+              type="text"
+              onChange={check}
+              onInput={(e) => {
+              // eslint-disable-next-line radix
+                e.target.value = e.target.value.slice(0, 21);
+              }}
+              onBlur={notEmpty}
+            />
+          </FormCont>
+          {(error.length === 0)
+            ? (
+              <Count
+                condition={(count === 0).toString()}
+              >
+                {count}
+                {' '}
+                Characters remaining
+              </Count>
+            )
+            : <Count condition="true">{error}</Count>}
+        </FieldData>
+
+        <FieldData>
+          <SecondLable>CSS Class</SecondLable>
+          <FormCont>
+            <Input
+              type="text"
+              id="css"
+              onChange={check}
+              placeholder="none"
+            />
+          </FormCont>
+          <Count>
+            Optional
+          </Count>
+        </FieldData>
+        <SplitArea>
+          <ColorData>
+            <SecondLable>Flair background color</SecondLable>
+            <Color
+              type="color"
+              id="bgColor"
+            />
+            {/* <div />
+            <div /> */}
+          </ColorData>
+        </SplitArea>
+        <SplitArea>
+          <ColorData>
+            <SecondLable>Flair text color</SecondLable>
+            <Color
+              type="color"
+              placeholder="Aa"
+              id="textColor"
+            />
+          </ColorData>
+        </SplitArea>
+      </Container>
+      <AddFlair>
+        <Save onClick={SendData}>
+          Save
+        </Save>
+        <Cancel onClick={cancel}>Cancel</Cancel>
+      </AddFlair>
+    </>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Post Flair_NewFlair_PostFlair.js.html b/docs/components_Moderation_Post Flair_NewFlair_PostFlair.js.html new file mode 100644 index 00000000..c315f207 --- /dev/null +++ b/docs/components_Moderation_Post Flair_NewFlair_PostFlair.js.html @@ -0,0 +1,86 @@ + + + + + JSDoc: Source: components/Moderation/Post Flair/NewFlair/PostFlair.js + + + + + + + + + + +
+ +

Source: components/Moderation/Post Flair/NewFlair/PostFlair.js

+ + + + + + +
+
+
import axios from '../../../../services/instance';
+/**
+ * Add New Flair
+ *
+ * @property {boolean} url - url to send data on
+ * @property {boolean} text - text flair
+ * @property {boolean} backgroundColor - background color for flair
+ * @property {boolean} textColor - text color
+ *
+ * @returns {object} provided response through backend
+ */
+
+const PostFlair = async (url, text, backgroundColor, textColor) => {
+  // const [data, setData] = useState(null);
+  // const [error, setError] = useState(null);
+  await axios.post(
+    url,
+    JSON.stringify({
+      text,
+      backgroundColor,
+      textColor,
+
+    }),
+  ).then((response) => {
+    console.log(response.status);
+    if (response?.status === 401) {
+      window.location.pathname = 'login';
+    }
+    return response.status;
+  }).catch((error) => {
+    console.log(error);
+    return false;
+  });
+};
+export default PostFlair;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Post Flair_PostFlair.jsx.html b/docs/components_Moderation_Post Flair_PostFlair.jsx.html new file mode 100644 index 00000000..59df216c --- /dev/null +++ b/docs/components_Moderation_Post Flair_PostFlair.jsx.html @@ -0,0 +1,175 @@ + + + + + JSDoc: Source: components/Moderation/Post Flair/PostFlair.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/Post Flair/PostFlair.jsx

+ + + + + + +
+
+
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
+import TableContainer from '@mui/material/TableContainer';
+import TableHead from '@mui/material/TableHead';
+import Paper from '@mui/material/Paper';
+
+import { useEffect, useMemo, useState } from 'react';
+import { useParams } from 'react-router-dom';
+import {
+  AboutString, Add, AddFlair, Body, IconBtn, LeftAlighne, POSTFLAIRPREVIEW,
+  StyledTooltip, TableHeader, TableHeaderCell, TableHeaderCellContainer, TableHeaderCellRes, TotalContainer,
+} from './style';
+import Entity from './Entity/Entity';
+import NewFlair from './NewFlair/NewFlair';
+import useFetch from '../../SubReddit/SideBar/Flirt/flirtServer';
+
+/**
+ * Post Flair
+ * @component
+ * @property  {function} handleClick disable all buttoms
+ * @property  {function} trueCan enable all buttoms
+ * @property  {function} save clase form and enable add
+ * @property  {function} cancel clase form and enable add
+ *
+ * @return {React.Component} - Post Flair
+ */
+export default function PostFlair() {
+  const [can, setCan] = useState(true);
+  const [add, setAdd] = useState(false);
+  const [flair, setFalir] = useState([]);
+  const { subReddit } = useParams();
+  const [data, dataError] = useFetch(subReddit);
+  console.log(data);
+
+  const value = useMemo(() => ({ data, dataError }), [data, dataError]);
+  console.log(value);
+
+  useEffect(() => {
+    setFalir(data);
+    console.log(dataError);
+  }, [flair, data]);
+
+  const handleClick = () => {
+    setCan(false);
+  };
+  const trueCan = () => {
+    setCan(true);
+  };
+  const save = () => {
+    setCan(true);
+    setAdd(false);
+  };
+  const cancel = () => {
+    setCan(true);
+    setAdd(false);
+  };
+  return (
+    <TotalContainer>
+      <AddFlair>
+        {can
+          ? <Add onClick={() => { setCan(false); setAdd(true); }}>Add Flair</Add>
+          : <Add disabled condition={!can}>Add Flair</Add>}
+      </AddFlair>
+      <LeftAlighne>
+        <AboutString>
+          Post flair management
+          <StyledTooltip
+            title="Learn more"
+          >
+            <IconBtn>
+              <ErrorOutlineIcon color="primary" sx={{ transform: 'rotate(180deg)', paddingTop: '5px' }} />
+            </IconBtn>
+          </StyledTooltip>
+        </AboutString>
+        <TableContainer component={Paper}>
+          <TableHeader aria-label="simple table">
+            <TableHead>
+              <TableHeaderCellContainer>
+                <POSTFLAIRPREVIEW>POST FLAIR PREVIEW</POSTFLAIRPREVIEW>
+                <TableHeaderCellRes align="center">
+                  CSS CLASS
+                  <StyledTooltip
+                    title="CSS classes determine the styling for flair in old Reddit"
+                  >
+                    <IconBtn>
+                      <ErrorOutlineIcon sx={{ transform: 'rotate(180deg)', color: 'gray', paddingTop: '5px' }} />
+                    </IconBtn>
+                  </StyledTooltip>
+                </TableHeaderCellRes>
+                <TableHeaderCellRes align="center">
+                  SETTINGS
+                  <StyledTooltip
+                    title="Shows if flair is mod-only, user editable, allows text, or allows emojis"
+                  >
+                    <IconBtn>
+                      <ErrorOutlineIcon sx={{ transform: 'rotate(180deg)', color: 'gray', paddingTop: '5px' }} />
+                    </IconBtn>
+                  </StyledTooltip>
+                </TableHeaderCellRes>
+                <TableHeaderCell align="center">
+                  FLAIR ID
+                  <StyledTooltip
+                    title="Use this ID when configuring automod to assign flair"
+                  >
+                    <IconBtn>
+                      <ErrorOutlineIcon sx={{ transform: 'rotate(180deg)', color: 'gray', paddingTop: '5px' }} />
+                    </IconBtn>
+                  </StyledTooltip>
+
+                </TableHeaderCell>
+              </TableHeaderCellContainer>
+            </TableHead>
+            <Body>
+              {flair?.map((row) => (
+                <Entity row={row} handleClick={handleClick} can={can} trueCan={trueCan} />
+              ))}
+            </Body>
+          </TableHeader>
+        </TableContainer>
+        {add
+        && <NewFlair save={save} cancel={cancel} />}
+      </LeftAlighne>
+    </TotalContainer>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_PostsAndComments_PostType_PostType.jsx.html b/docs/components_Moderation_PostsAndComments_PostType_PostType.jsx.html new file mode 100644 index 00000000..435ed9bd --- /dev/null +++ b/docs/components_Moderation_PostsAndComments_PostType_PostType.jsx.html @@ -0,0 +1,116 @@ + + + + + JSDoc: Source: components/Moderation/PostsAndComments/PostType/PostType.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/PostsAndComments/PostType/PostType.jsx

+ + + + + + +
+
+
import { Switch } from '@mui/material';
+import {
+  AboutString,
+  Disc,
+  FlexBox,
+  FlexBoxColumn,
+} from './style';
+/**
+ * Posts Type
+ * @component
+ * @property  {function} setallowImgs - set allow image or not
+ * @property  {function} setallowVideos - set allow image or not
+ * @property  {function} setallowLinks - set allow image or not
+ *
+ * @param {string} allowImgs -  allow image or not
+ * @param {string} allowVideos -  allow video or not
+ * @param {string} allowLinks -  allow links or not
+ *
+ * @return {React.Component} - Posts Type
+ */
+export default function PostType(props) {
+  const {
+    allowImgs, allowVideos, allowLinks, setallowImgs, setallowVideos, setallowLinks,
+  } = props;
+  return (
+    <>
+      <FlexBox>
+        <FlexBoxColumn>
+          <AboutString>
+            Image posts
+          </AboutString>
+          <Disc>Allow images to be uploaded in posts in your subreddit</Disc>
+        </FlexBoxColumn>
+        { allowImgs
+                    && <Switch defaultChecked onClick={() => { setallowImgs(!allowImgs); }} />}
+        {!allowImgs
+                    && <Switch defaultChecked={false} onClick={() => { setallowImgs(!allowImgs); }} />}
+      </FlexBox>
+      <FlexBox>
+        <FlexBoxColumn>
+          <AboutString>
+            Videos posts
+          </AboutString>
+          <Disc>Allow videos to be uploaded in posts in your subreddit</Disc>
+        </FlexBoxColumn>
+        { allowVideos
+                    && <Switch defaultChecked onClick={() => { setallowVideos(!allowVideos); }} />}
+        {!allowVideos
+                    && <Switch defaultChecked={false} onClick={() => { setallowVideos(!allowVideos); }} />}
+      </FlexBox>
+      <FlexBox>
+        <FlexBoxColumn>
+          <AboutString>
+            Links posts
+          </AboutString>
+          <Disc>Allow links to be uploaded in posts in your subreddit</Disc>
+        </FlexBoxColumn>
+        { allowLinks
+                    && <Switch defaultChecked onClick={() => { setallowLinks(!allowLinks); }} />}
+        {!allowLinks
+                    && <Switch defaultChecked={false} onClick={() => { setallowLinks(!allowLinks); }} />}
+      </FlexBox>
+    </>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_PostsAndComments_PostsAndComments.jsx.html b/docs/components_Moderation_PostsAndComments_PostsAndComments.jsx.html new file mode 100644 index 00000000..6f86a9e2 --- /dev/null +++ b/docs/components_Moderation_PostsAndComments_PostsAndComments.jsx.html @@ -0,0 +1,164 @@ + + + + + JSDoc: Source: components/Moderation/PostsAndComments/PostsAndComments.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/PostsAndComments/PostsAndComments.jsx

+ + + + + + +
+
+
import { Box, Typography } from '@mui/material';
+import { useEffect, useState, useMemo } from 'react';
+
+import { useParams } from 'react-router-dom';
+import patchData from '../../SubReddit/SideBar/Mderation/ModerationServer';
+import FormDialog from '../../HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/PopUp';
+import getSubredditAllData from '../../SubReddit/SubrridetDataServer';
+import PostType from './PostType/PostType';
+import {
+  AboutString, AboutSubString, Add, AddFlair, BackHomeButton, Container,
+  Disc, FlexBox, FlexBoxColumn, LeftAlighne, NotFoundBox, NotFountImage, SortString, TotalContainer,
+} from './style';
+import SuggestionSort from './SuggestionSort/SuggestionSort';
+import Done from '../../AlertMessage';
+
+/**
+ * Posts And Comments
+ * @component
+ * @property  {function} redirect redirect to home page
+ * @property  {function} createCommunity show create community form
+ * @property  {function} SendData send data to backend
+ *
+ * @return {React.Component} - Posts And Comments
+ */
+
+function PostsAndComments() {
+  const { subReddit } = useParams();
+  const [exist, setExist] = useState(true);
+  const [showPopUp, setShowPopUp] = useState(false);
+  const [allowImgs, setallowImgs] = useState(false);
+  const [allowVideos, setallowVideos] = useState(false);
+  const [allowLinks, setallowLinks] = useState(false);
+  const [suggestedSort, setSuggestedSort] = useState('');
+
+  const [data, dataError, statusCode] = getSubredditAllData(subReddit);
+  const value = useMemo(() => ({ data, dataError }), [data, dataError]);
+  console.log(value, data);
+  useEffect(() => {
+    if (statusCode === 404) {
+      setExist(false);
+    }
+    setallowImgs(data?.allowImgs);
+    setallowVideos(data?.allowVideos);
+    setallowLinks(data?.allowLinks);
+    setSuggestedSort(data?.suggestedSort);
+    console.log(suggestedSort);
+  }, [data, statusCode]);
+
+  const redirect = () => {
+    window.location.pathname = '/';
+  };
+
+  const createCommunity = async () => {
+    await setShowPopUp(true);
+    const ele = document.getElementById('popup-form-button');
+    ele.click();
+  };
+  const SendData = () => {
+    patchData(subReddit, {
+      allowImgs,
+      allowVideos,
+      allowLinks,
+      suggestedSort,
+    }); // fetch api
+    Done('Chnges Saved');
+  };
+  return (
+    exist
+      ? (
+        <TotalContainer>
+          <AddFlair><Add onClick={SendData}>Save Change</Add></AddFlair>
+          <LeftAlighne>
+            <Container>
+              <AboutString>
+                Posts and Comment settings
+              </AboutString>
+              <Disc sx={{ marginTop: '20px' }}>Comments</Disc>
+              <FlexBox>
+                <FlexBoxColumn>
+                  <SortString>
+                    Suggested sort
+                  </SortString>
+                  <Disc>All comment feeds in community will default to this sort setting</Disc>
+                </FlexBoxColumn>
+                {suggestedSort
+                && <SuggestionSort suggestedSort={suggestedSort} setSuggestedSort={setSuggestedSort} />}
+              </FlexBox>
+              <Disc>posts</Disc>
+
+              <AboutSubString>
+                Post type options
+              </AboutSubString>
+
+              <PostType allowImgs={allowImgs} allowVideos={allowVideos} allowLinks={allowLinks} setallowImgs={setallowImgs} setallowVideos={setallowVideos} setallowLinks={setallowLinks} />
+
+            </Container>
+          </LeftAlighne>
+        </TotalContainer>
+      ) : (
+        <NotFoundBox>
+          <NotFountImage src="https://www.redditstatic.com/desktop2x/img/snoomoji/snoo_thoughtful.png" />
+          <Typography sx={{ fontWeight: 700, marginBottom: 2, fontSize: '18px' }}>Sorry, there arenโ€™t any communities on Reddit with that name.</Typography>
+          <Typography sx={{ marginBottom: 4, fontSize: '14px' }}>This community may have been banned or the community name is incorrect.</Typography>
+          <Box>
+            <BackHomeButton variant="outlined" onClick={createCommunity} sx={{ textTransform: 'unset' }}>Create community</BackHomeButton>
+            <BackHomeButton variant="contained" onClick={redirect}>Go Home</BackHomeButton>
+          </Box>
+          {showPopUp && <Box sx={{ display: 'absolute' }}><FormDialog display="none" /></Box>}
+        </NotFoundBox>
+      )
+  );
+}
+export default PostsAndComments;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_PostsAndComments_SuggestionSort_SuggestionSort.jsx.html b/docs/components_Moderation_PostsAndComments_SuggestionSort_SuggestionSort.jsx.html new file mode 100644 index 00000000..199e4308 --- /dev/null +++ b/docs/components_Moderation_PostsAndComments_SuggestionSort_SuggestionSort.jsx.html @@ -0,0 +1,110 @@ + + + + + JSDoc: Source: components/Moderation/PostsAndComments/SuggestionSort/SuggestionSort.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/PostsAndComments/SuggestionSort/SuggestionSort.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import { useState } from 'react';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
+import {
+  Select, SelectBox, Selected, SelectItem,
+} from './style';
+/**
+ * Suggestion Sort
+ * @component
+ * @property  {function} handleClick1 oggle the list when click
+ * @property  {function} handleClickAway1 handle disable the list when click away
+ *
+ * @return {React.Component} - Suggestion Sort
+ */
+export default function SuggestionSort(props) {
+  const { suggestedSort, setSuggestedSort } = props;
+  const [showList1, setShowList1] = useState(false);
+  // const [type, setType] = useState({ suggestedSort });
+
+  // toggle the list when click
+  const handleClick1 = () => {
+    setShowList1((prev) => !prev);
+  };
+
+  // handle disable the list when click away
+  const handleClickAway1 = () => {
+    setShowList1(false);
+  };
+  return (
+    <>
+      <Select>
+        <ClickAwayListener onClickAway={handleClickAway1}>
+          <Box data-testid="sort" sx={{ display: 'flex', alignItems: 'center' }} onClick={() => { handleClick1(); }}>
+            <Box sx={{ display: 'flex', alignItems: 'flex-end', flexDirection: 'column' }}>
+              <Selected>
+                {suggestedSort}
+              </Selected>
+            </Box>
+            <ExpandMoreIcon />
+          </Box>
+        </ClickAwayListener>
+      </Select>
+      {showList1 && (
+      <SelectBox data-testid="items">
+        {/* <SelectItem onClick={() => { setType('None (Recommended)'); }} condition={(type === 'None (Recommended)')}>None (Recommended)</SelectItem> */}
+        <SelectItem onClick={() => { setSuggestedSort('best'); }} condition={(suggestedSort === 'best')}>Best</SelectItem>
+        <SelectItem onClick={() => { setSuggestedSort('old'); }} condition={(suggestedSort === 'old')}>Old</SelectItem>
+        <SelectItem onClick={() => { setSuggestedSort('top'); }} condition={(suggestedSort === 'top')}>Top</SelectItem>
+        {/* <SelectItem onClick={() => { setType('Q&A'); }} condition={(type === 'Q&A')}>Q&A</SelectItem> */}
+        {/* <SelectItem onClick={() => { setType('Live (Beta)'); }} condition={(type === 'Live (Beta)')}>Live (Beta)</SelectItem> */}
+        {/* <SelectItem onClick={() => { setType('Controvesial'); }} condition={(type === 'Controvesial')}>Controvesial</SelectItem> */}
+        <SelectItem onClick={() => { setSuggestedSort('new'); }} condition={(suggestedSort === 'new')}>New</SelectItem>
+      </SelectBox>
+      )}
+    </>
+
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Rules_AddRule_AddRyle.jsx.html b/docs/components_Moderation_Rules_AddRule_AddRyle.jsx.html new file mode 100644 index 00000000..7e9236c4 --- /dev/null +++ b/docs/components_Moderation_Rules_AddRule_AddRyle.jsx.html @@ -0,0 +1,272 @@ + + + + + JSDoc: Source: components/Moderation/Rules/AddRule/AddRyle.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/Rules/AddRule/AddRyle.jsx

+ + + + + + +
+
+
import * as React from 'react';
+import Button from '@mui/material/Button';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContentText from '@mui/material/DialogContentText';
+import { Divider, IconButton } from '@mui/material';
+import CloseIcon from '@mui/icons-material/Close';
+import { useParams } from 'react-router-dom';
+import {
+  Add, Cancel, Container, Count, Dial, DialCont, Disc, FullDiscTextArea, Lable, TextArea, Title, TitleString,
+} from './style';
+import RadioBtn from './Radio/Radio';
+import PostRule from './PostRuleServer';
+import EditRule from './EditRuleServer';
+import DeleteRule from './DeleteServer';
+
+/**
+ * Add Rule
+ * @component
+ * @property  {function} handleClickOpen open rule form
+ * @property  {function} handleClose close rule form
+ * @property  {function} myType set the rule type
+ * @property  {function} check check the title length
+ * @property  {function} check2 check the default name length
+ * @property  {function} check3 check the description length
+ * @property  {function} SendData send data to backend
+ *
+ * @return {React.Component} - Add Rule
+ */
+
+export default function AddRule(props) {
+  const { rule } = props;
+  const [open, setOpen] = React.useState(false);
+  const [can, setCan] = React.useState(false);
+
+  const [count, setCount] = React.useState(100);
+  const [count2, setCount2] = React.useState(100);
+  const [count3, setCount3] = React.useState(500);
+  const [edit, setEdit] = React.useState(false);
+
+  const { subReddit } = useParams();
+
+  const [type, setType] = React.useState('Posts&comments');
+
+  React.useEffect(() => {
+    if (rule) {
+      setCount(100 - rule.title.length);
+      setCount2(100 - rule.defaultName.length);
+      setCount3(500 - rule.description.length);
+      setEdit(true);
+    }
+    if (count < 100) { setCan(true); } else { setCan(false); }
+    console.log(can);
+  }, [count, rule]);
+
+  React.useEffect(() => {
+    if (rule?.appliesTo) {
+      setType(rule?.appliesTo);
+    } else {
+      setType('Posts&comments');
+    }
+  }, [rule]);
+  const handleClickOpen = () => {
+    setOpen(true);
+  };
+
+  const handleClose = () => {
+    setOpen(false);
+  };
+  const myType = (t) => {
+    setType(t);
+  };
+  const check = (e) => {
+    const ele = e?.target?.value;
+    if (100 - ele.length >= 0) { setCount(100 - ele.length); }
+  };
+  const check2 = (e) => {
+    const ele = e?.target?.value;
+    if (100 - ele.length >= 0) { setCount2(100 - ele.length); }
+  };
+  const check3 = (e) => {
+    const ele = e?.target?.value;
+    if (500 - ele.length >= 0) { setCount3(500 - ele.length); }
+  };
+
+  const SendData = () => {
+    const defaultName = document.getElementById('defaultName').value;
+    const title = document.getElementById('title').value;
+    const description = document.getElementById('description').value;
+    console.log(title, defaultName, description);
+    if (edit) {
+      EditRule(subReddit, rule?.title, {
+        title,
+        defaultName,
+        description,
+        type,
+      });
+    } else {
+      PostRule(`subreddits/${subReddit}/rules/${title}`, defaultName, description, type);
+    }
+    handleClose();
+  };
+  const DeleteData = () => {
+    const title = document.getElementById('title').value;
+    console.log(title);
+    DeleteRule(subReddit, title);
+    handleClose();
+  };
+  return (
+    <div>
+      <Button variant="outlined" onClick={handleClickOpen} sx={{ display: 'none' }} id="add">
+        Open form dialog
+      </Button>
+      <Container>
+        <Dial open={open} onClose={handleClose}>
+          <Title>
+            <TitleString>Add rule</TitleString>
+            <IconButton onClick={handleClose}><CloseIcon /></IconButton>
+          </Title>
+          <Divider />
+          <DialCont>
+            <DialogContentText>
+              <Lable>Rule</Lable>
+            </DialogContentText>
+            <TextArea
+              defaultValue={rule?.title}
+              id="title"
+              placeholder='Rule displayed (e.g. "No photos")'
+              onChange={check}
+              onInput={(e) => {
+                // eslint-disable-next-line radix
+                e.target.value = e.target.value.slice(0, 100);
+              }}
+            />
+            <Count
+              condition={(count === 0).toString()}
+            >
+              {count}
+              {' '}
+              Characters remaining
+            </Count>
+            <RadioBtn myType={myType} type={(rule?.appliesTo) ? rule?.appliesTo : 'Posts&comments'} />
+            <DialogContentText>
+              <Lable marginTop="-19px">Report reason</Lable>
+              <Disc>Defaults to rule name if left blank</Disc>
+            </DialogContentText>
+            <TextArea
+              id="defaultName"
+              defaultValue={rule?.defaultName}
+              placeholder='Reason rule is broken (e.g. "This is a photos")'
+              onChange={check2}
+              onInput={(e) => {
+                // eslint-disable-next-line radix
+                e.target.value = e.target.value.slice(0, 100);
+              }}
+            />
+            <Count
+              condition={(count2 === 0).toString()}
+            >
+              {count2}
+              {' '}
+              Characters remaining
+            </Count>
+            <DialogContentText>
+              <Lable marginTop="11px">Full description</Lable>
+            </DialogContentText>
+            <FullDiscTextArea
+              id="description"
+              defaultValue={rule?.description}
+              placeholder="Enter the Full description of the rule"
+              onChange={check3}
+              onInput={(e) => {
+                // eslint-disable-next-line radix
+                e.target.value = e.target.value.slice(0, 500);
+              }}
+            />
+            <Count
+              condition={(count3 === 0).toString()}
+            >
+              {count3}
+              {' '}
+              Characters remaining
+            </Count>
+          </DialCont>
+          <DialogActions>
+            {(can)
+              ? (
+                (edit)
+                  ? (
+                    <>
+                      <Cancel onClick={DeleteData}>Delete</Cancel>
+                      <Add onClick={SendData}>Save</Add>
+                    </>
+                  )
+                  : (
+                    <>
+                      <Cancel onClick={handleClose}>Cancel</Cancel>
+                      <Add onClick={SendData}>Add Rule</Add>
+                    </>
+                  )
+              )
+              : (
+                (edit)
+                  ? (
+                    <>
+                      <Cancel disabled>Delete</Cancel>
+                      <Add disabled>Save</Add>
+                    </>
+                  )
+                  : (
+                    <>
+                      <Cancel disabled>Cancel</Cancel>
+                      <Add disabled>Add Rule</Add>
+                    </>
+                  )
+              )}
+          </DialogActions>
+        </Dial>
+      </Container>
+    </div>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Rules_AddRule_DeleteServer.js.html b/docs/components_Moderation_Rules_AddRule_DeleteServer.js.html new file mode 100644 index 00000000..42d27411 --- /dev/null +++ b/docs/components_Moderation_Rules_AddRule_DeleteServer.js.html @@ -0,0 +1,73 @@ + + + + + JSDoc: Source: components/Moderation/Rules/AddRule/DeleteServer.js + + + + + + + + + + +
+ +

Source: components/Moderation/Rules/AddRule/DeleteServer.js

+ + + + + + +
+
+
import axios from '../../../../services/instance';
+/**
+ * Delete rule
+ *
+ * @property {string} Name - name of subreddit
+ * @property {integer} id - id of rule
+ *
+ */
+const DeleteRule = async (Name, id) => {
+  let statusCode = '';
+  await axios.delete(`subreddits/${Name}/rules/${id}`)
+    .then((response) => {
+      statusCode = response.status;
+    }).catch((error) => {
+      statusCode = error.response.status;
+      console.log(error);
+    });
+  if (statusCode === 401) {
+    window.location.pathname = 'login';
+  }
+};
+export default DeleteRule;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Rules_AddRule_EditRuleServer.js.html b/docs/components_Moderation_Rules_AddRule_EditRuleServer.js.html new file mode 100644 index 00000000..23e3d21f --- /dev/null +++ b/docs/components_Moderation_Rules_AddRule_EditRuleServer.js.html @@ -0,0 +1,76 @@ + + + + + JSDoc: Source: components/Moderation/Rules/AddRule/EditRuleServer.js + + + + + + + + + + +
+ +

Source: components/Moderation/Rules/AddRule/EditRuleServer.js

+ + + + + + +
+
+
import Done from '../../../AlertMessage';
+import axios from '../../../../services/instance';
+/**
+ * Edit rule
+ *
+ * @property {string} Name - name of subreddit
+ * @property {integer} id - id of rule
+ *
+ */
+const EditRule = async (Name, id, prefs) => {
+  let statusCode = '';
+  await axios.patch(`subreddits/${Name}/rules/${id}`, prefs).then((response) => {
+    statusCode = response.status;
+  }).catch((error) => {
+    statusCode = error.response.status;
+    console.log(error);
+  });
+  if (statusCode === 200 || statusCode === 204) {
+    Done('Rule Edited');
+  }
+  if (statusCode === 401) {
+    window.location.pathname = 'login';
+  }
+};
+export default EditRule;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Rules_AddRule_PostRuleServer.js.html b/docs/components_Moderation_Rules_AddRule_PostRuleServer.js.html new file mode 100644 index 00000000..f9cc4553 --- /dev/null +++ b/docs/components_Moderation_Rules_AddRule_PostRuleServer.js.html @@ -0,0 +1,87 @@ + + + + + JSDoc: Source: components/Moderation/Rules/AddRule/PostRuleServer.js + + + + + + + + + + +
+ +

Source: components/Moderation/Rules/AddRule/PostRuleServer.js

+ + + + + + +
+
+
import axios from '../../../../services/instance';
+import Done from '../../../AlertMessage';
+
+/**
+ * Post new rule
+ *
+ * @property {string} url - url to post data
+ * @property {string} defaultName - name for rule
+ * @property {string} description - description of rule
+ * @property {string} appliesTo - applies to in rule
+
+ */
+
+const PostRule = async (url, defaultName, description, appliesTo) => {
+  await axios.post(
+    url,
+    JSON.stringify({
+      defaultName,
+      description,
+      appliesTo,
+    }),
+  ).then((response) => {
+    console.log(response.status);
+    if (response?.status === 401) {
+      window.location.pathname = 'login';
+    }
+    if (response?.status === 200 || response?.status === 204) {
+      Done('Rule Added');
+    }
+    return response.status;
+  }).catch((error) => {
+    console.log(error);
+    return false;
+  });
+};
+export default PostRule;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Rules_AddRule_Radio_Radio.jsx.html b/docs/components_Moderation_Rules_AddRule_Radio_Radio.jsx.html new file mode 100644 index 00000000..297968d1 --- /dev/null +++ b/docs/components_Moderation_Rules_AddRule_Radio_Radio.jsx.html @@ -0,0 +1,109 @@ + + + + + JSDoc: Source: components/Moderation/Rules/AddRule/Radio/Radio.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/Rules/AddRule/Radio/Radio.jsx

+ + + + + + +
+
+
import {
+  DialogContentText,
+  FormControl, FormControlLabel, Radio, RadioGroup,
+} from '@mui/material';
+// import React from 'react';
+import {
+  Cont, ContUp, Lable, Name,
+} from './style';
+/**
+   *@component
+   * @param {object} props
+   * @return {React.Component} -radio button in  pop up form
+   */
+function RadioBtn(props) {
+  const { myType, type } = props;
+  console.log(type);
+  // React.useEffect(() => {
+  //   if (type) {
+  //     myType(type);
+  //   } else {
+  //     myType('Posts&comments');
+  //   }
+  // }, [type]);
+  return (
+    <>
+      <DialogContentText><Lable> Applies to</Lable></DialogContentText>
+      <FormControl sx={{ marginBottom: '30px' }}>
+        <RadioGroup
+          aria-labelledby="demo-radio-buttons-group-label"
+          name="radio-buttons-group"
+          id="type"
+          defaultValue={type}
+          onChange={(e) => myType(e.target.value)}
+        >
+          <ContUp>
+            <Cont>
+              <FormControlLabel value="Posts&comments" control={<Radio />} sx={{ margin: 0 }} />
+              <Name>Posts & comments</Name>
+            </Cont>
+          </ContUp>
+          <ContUp>
+            <Cont>
+              <FormControlLabel value="PostsOnly" control={<Radio />} sx={{ margin: 0 }} />
+              <Name>Posts only</Name>
+            </Cont>
+          </ContUp>
+          <ContUp>
+            <Cont>
+              <FormControlLabel value="CommentsOnly" control={<Radio />} sx={{ margin: 0 }} />
+              <Name>Comments only</Name>
+            </Cont>
+          </ContUp>
+        </RadioGroup>
+      </FormControl>
+    </>
+  );
+}
+export default RadioBtn;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Rules_Entity_Entity.jsx.html b/docs/components_Moderation_Rules_Entity_Entity.jsx.html new file mode 100644 index 00000000..ef805534 --- /dev/null +++ b/docs/components_Moderation_Rules_Entity_Entity.jsx.html @@ -0,0 +1,118 @@ + + + + + JSDoc: Source: components/Moderation/Rules/Entity/Entity.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/Rules/Entity/Entity.jsx

+ + + + + + +
+
+
import { IconButton } from '@mui/material';
+import CreateIcon from '@mui/icons-material/Create';
+import UnfoldLessOutlinedIcon from '@mui/icons-material/UnfoldLessOutlined';
+import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined';
+import { useState } from 'react';
+import {
+  Actions,
+  Details, ElementBox, MoreData, MoreDetails, MoreDetailsHeader, Num, Row, Text,
+} from './style';
+
+/**
+ * Entity of Rule
+ * @component
+ * @property  {function} handleExpand show more details
+ *
+ * @return {React.Component} - Entity of Rule
+ */
+
+function Entity(props) {
+  const {
+    row, index, setefitRule,
+  } = props;
+  const [expand, setExpand] = useState();
+
+  const handleExpand = () => {
+    setExpand((prev) => !prev);
+  };
+  return (
+    <>
+      <Row>
+        <Actions>
+          <Num>{index + 1}</Num>
+          <Text>{row?.title}</Text>
+        </Actions>
+        <Actions>
+          <IconButton onClick={() => { setefitRule(row); const ele = document.getElementById('add'); ele.click(); }}><CreateIcon /></IconButton>
+          <ElementBox>
+            {expand ? <UnfoldLessOutlinedIcon sx={{ rotate: '-45deg' }} onClick={() => { handleExpand(); }} />
+              : <UnfoldMoreOutlinedIcon sx={{ rotate: '-45deg' }} onClick={() => { handleExpand(); }} />}
+          </ElementBox>
+        </Actions>
+      </Row>
+      {expand
+      && (
+      <MoreData>
+        <Details>
+          <MoreDetailsHeader>Report reason</MoreDetailsHeader>
+          <MoreDetails>{row?.title}</MoreDetails>
+        </Details>
+        <Details>
+          <MoreDetailsHeader>APPLIES TO</MoreDetailsHeader>
+          <MoreDetails>{row?.appliesTo}</MoreDetails>
+        </Details>
+        <Details>
+          <MoreDetailsHeader>CREATED</MoreDetailsHeader>
+          <MoreDetails>{row?.createdAt}</MoreDetails>
+        </Details>
+        <Details>
+          <MoreDetailsHeader>FULL DESCRIPTION</MoreDetailsHeader>
+          <MoreDetails>{row?.description}</MoreDetails>
+        </Details>
+      </MoreData>
+      )}
+    </>
+  );
+}
+export default Entity;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Moderation_Rules_Rules.jsx.html b/docs/components_Moderation_Rules_Rules.jsx.html new file mode 100644 index 00000000..af74e3e4 --- /dev/null +++ b/docs/components_Moderation_Rules_Rules.jsx.html @@ -0,0 +1,115 @@ + + + + + JSDoc: Source: components/Moderation/Rules/Rules.jsx + + + + + + + + + + +
+ +

Source: components/Moderation/Rules/Rules.jsx

+ + + + + + +
+
+
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
+import { useEffect, useMemo, useState } from 'react';
+import { useParams } from 'react-router-dom';
+import getSubredditAllData from '../../SubReddit/SubrridetDataServer';
+import AddRule from './AddRule/AddRyle';
+import Entity from './Entity/Entity';
+import {
+  AboutDisc, AboutString, Add, AddFlair, Header, IconBtn, LeftAlighne, StyledTooltip, TotalContainer,
+} from './style';
+
+/**
+ * Rules
+ * @component
+ *
+ * @return {React.Component} - Rules
+ */
+
+export default function Rules() {
+  const [rules, setRules] = useState([]);
+  const [editRule, setefitRule] = useState();
+
+  const { subReddit } = useParams();
+  const [data, dataError] = getSubredditAllData(subReddit);
+  const value = useMemo(() => ({ data, dataError }), [data, dataError]);
+  useEffect(() => {
+    setRules(data?.rules);
+    console.log(dataError);
+  }, [rules, data]);
+
+  console.log(value);
+
+  return (
+    <TotalContainer>
+      <AddFlair>
+        <Add onClick={() => { const ele = document.getElementById('add'); setefitRule(null); ele.click(); }}>Add Rule</Add>
+        <AddRule rule={editRule} />
+      </AddFlair>
+      <LeftAlighne>
+        <Header>
+          <AboutString>
+            Rules
+            <StyledTooltip
+              title="Learn more"
+            >
+              <IconBtn>
+                <ErrorOutlineIcon color="primary" sx={{ transform: 'rotate(180deg)', paddingTop: '5px' }} />
+              </IconBtn>
+            </StyledTooltip>
+          </AboutString>
+          <AboutDisc>
+            These are rules that visitors must follow to participate.
+            They can be used as reasons to report or ban posts,
+            comments, and users. Communities can have a maximum of 15 rules.
+          </AboutDisc>
+        </Header>
+        <TotalContainer>
+          {rules?.map((row, index) => (
+            <Entity row={row} index={index} setefitRule={setefitRule} />
+          ))}
+        </TotalContainer>
+      </LeftAlighne>
+    </TotalContainer>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Notifications_NotificationsBody_NotificationCategories_NotificationCategories.jsx.html b/docs/components_Notifications_NotificationsBody_NotificationCategories_NotificationCategories.jsx.html new file mode 100644 index 00000000..2ce76c00 --- /dev/null +++ b/docs/components_Notifications_NotificationsBody_NotificationCategories_NotificationCategories.jsx.html @@ -0,0 +1,239 @@ + + + + + JSDoc: Source: components/Notifications/NotificationsBody/NotificationCategories/NotificationCategories.jsx + + + + + + + + + + +
+ +

Source: components/Notifications/NotificationsBody/NotificationCategories/NotificationCategories.jsx

+ + + + + + +
+
+
/* eslint-disable consistent-return */
+/* eslint-disable import/no-cycle */
+import { useContext, createContext, useEffect } from 'react';
+import IconButton from '@mui/material/IconButton';
+import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
+import moment from 'moment/moment';
+import { useCookies } from 'react-cookie';
+import { useNavigate } from 'react-router-dom';
+import { CategoriesContext } from '../NotificationsBody';
+import { notificationMarkRead } from '../../notificationsServer';
+import {
+  Notification, Options, MenuOptions, NotificationTime,
+  NotificationBody, BodyHead, Body, ContainerHead, SeeMore,
+} from './styles';
+import NotificationImages from './NotificationImage/NotificationImages';
+import { redditCookie } from '../../../Authentication/authenticationServer';
+
+export const ReplayContext = createContext();
+/**
+ *  Notification Categories
+ *  @component
+ * @param {Array} earlier - Array of earlier notifications
+ * @param {Array} today - type of today notifiactions
+ * @param {Function} handleClose - function to set what notifiacation we select and it's type
+ * @param {Function} handleClick - function to handel deleteing when click hide
+ * @param {Boolean} open - bool to set open or close
+ * @param {object} anchorEl - anchor element
+ * @return {React.Component} - Retrun all notificaions dependent on type today or earlier
+ */
+function NotificationCategories({ NavBar }) {
+  const {
+    earlier, today, handleClose, handleClick, open, anchorEl,
+  } = useContext(CategoriesContext);
+  // options of see more
+  const options = ['Hide this notification'];
+  // to set today or earlier
+  const [cookies, setCookies] = useCookies(['redditUser']);
+  const navigate = useNavigate();
+  const value = (today) || earlier;
+  moment.updateLocale('en', {
+    relativeTime: {
+      past: '%s ',
+      ago: '',
+      s: 'now',
+      mm: '%dm',
+      hh: '%dh',
+      dd: '%dd',
+      MM: moment().format('MMM d'),
+      yy: '%dy',
+    },
+  });
+  useEffect(() => {
+    redditCookie(setCookies);
+  }, []);
+  const follwed = (ele) => {
+    const follow = (ele?.followedSubreddit) ? `r/${ele?.followedSubreddit.fixedName}` : `u/${cookies?.redditUser.userName}`;
+    if (ele?.type === 'follow') {
+      return 'New follower!';
+    } if (ele?.type === 'postReply') {
+      const temp = `u/${ele?.followerUser.userName} replied to your post in `;
+      return temp + follow;
+    }
+    if (ele?.type === 'commentReply') {
+      const temp = `u/${ele?.followerUser.userName} replied to your comment in `;
+      return temp + follow;
+    }
+    if (ele?.type === 'userMention') {
+      const temp = `u/${ele?.followerUser.userName} mentioned you in `;
+      return temp;
+    }
+    if (ele?.type === 'firstPostUpVote' || ele?.type === 'firstCommentUpVote') {
+      const temp = 'โฌ†๏ธ 1st upvote!';
+      return temp;
+    }
+    return '';
+  };
+  const body = (ele) => {
+    const follow = (ele?.followedSubreddit) ? `r/${ele?.followedSubreddit.fixedName}` : `u/${cookies?.redditUser.userName}`;
+    if (ele?.type === 'follow') {
+      return `${ele.followerUser.userName} followed you. Start a chat!`;
+    } if (ele?.type === 'postReply') {
+      const temp = `${ele?.comment.text}`;
+      return temp;
+    }
+    if (ele?.type === 'commentReply') {
+      const temp = `${ele?.comment.text}  `;
+      return temp;
+    }
+    if (ele?.type === 'userMention') {
+      const temp = `${ele?.comment.text}`;
+      return temp;
+    }
+    if (ele?.type === 'firstPostUpVote') {
+      const temp = 'Go see your comment on ';
+      return temp + follow;
+    }
+    if (ele?.type === 'firstCommentUpVote') {
+      const temp = 'Go see your comment on ';
+      return temp + follow;
+    }
+    return '';
+  };
+  const handleLink = (ele) => {
+    const follow = (ele?.followedSubreddit) ? `/r/${ele?.followedSubreddit.fixedName}` : `/user/${cookies?.redditUser.userName}`;
+    if (!ele.seen) { notificationMarkRead(ele._id); }
+    if (ele?.type === 'follow') {
+      navigate(`/user/${ele.followerUser.userName}`);
+    } else {
+      navigate(`${follow}/comments/${ele.post}`);
+    }
+  };
+  return (
+    <div data-testid={`notification-categories-${today ? 'today' : 'earlier'}`}>
+      { value?.map((element, indx) => (
+        <Notification seen={!element.seen} key={`${indx + 0}`}>
+          <ReplayContext.Provider value={element?.type}>
+            <NotificationImages image={element.followerUser?.profilePicture} />
+          </ReplayContext.Provider>
+          <NotificationBody onClick={() => { handleLink(element); }}>
+            <ContainerHead>
+              <BodyHead>
+                {follwed(element)}
+                <NotificationTime>
+                  { ' ยท ' }
+                  { (moment.utc(element.createdAt).local().startOf('seconds')
+                    .fromNow())}
+                </NotificationTime>
+              </BodyHead>
+              {(!NavBar)
+                ? (
+                  <SeeMore>
+                    <IconButton
+                      data-testid="seeMore"
+                      id="long-button"
+                      aria-controls={open ? 'long-menu' : undefined}
+                      aria-expanded={open ? 'true' : undefined}
+                      aria-haspopup="true"
+                      catorige={(today) ? 'today' : 'earlier'}
+                      onClick={(e) => { handleClick(e, element._id); }}
+                    >
+                      <MoreHorizIcon />
+                    </IconButton>
+                    <MenuOptions
+                      data-testid="options"
+                      anchorOrigin={{
+                        vertical: 'bottom',
+                        horizontal: 'right',
+                      }}
+                      transformOrigin={{
+                        vertical: 'top',
+                        horizontal: 'right',
+                      }}
+                      id="long-menu"
+                      anchorEl={anchorEl}
+                      open={open}
+                      onClose={handleClose}
+                      MenuListProps={{
+                        'aria-labelledby': 'long-button',
+                      }}
+                    >
+                      {options.map((option) => (
+                        <Options
+                          key={option}
+                          selected={option === 'Pyxis'}
+                          onClick={handleClose}
+                        >
+                          {option}
+                        </Options>
+                      ))}
+                    </MenuOptions>
+                  </SeeMore>
+                ) : null}
+            </ContainerHead>
+            <Body>
+              { body(element).replace(/<[^>]+>/g, '').slice(0, 200) }
+              {
+                body(element).length > 200 && '...'
+              }
+            </Body>
+          </NotificationBody>
+        </Notification>
+
+      ))}
+    </div>
+  );
+}
+
+export default NotificationCategories;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Notifications_NotificationsBody_NotificationCategories_NotificationImage_NotificationImages.jsx.html b/docs/components_Notifications_NotificationsBody_NotificationCategories_NotificationImage_NotificationImages.jsx.html new file mode 100644 index 00000000..cd249809 --- /dev/null +++ b/docs/components_Notifications_NotificationsBody_NotificationCategories_NotificationImage_NotificationImages.jsx.html @@ -0,0 +1,109 @@ + + + + + JSDoc: Source: components/Notifications/NotificationsBody/NotificationCategories/NotificationImage/NotificationImages.jsx + + + + + + + + + + +
+ +

Source: components/Notifications/NotificationsBody/NotificationCategories/NotificationImage/NotificationImages.jsx

+ + + + + + +
+
+
/* eslint-disable import/no-cycle */
+import { useContext } from 'react';
+import NotificationsIcon from '@mui/icons-material/Notifications';
+import ModeCommentIcon from '@mui/icons-material/ModeComment';
+import PersonIcon from '@mui/icons-material/Person';
+import FavoriteIcon from '@mui/icons-material/Favorite';
+import {
+  ImageContiner, ChildImage, NotificationImage,
+} from './styles';
+import { ReplayContext } from '../NotificationCategories';
+
+/**
+ * NotificationImages
+ *  @component
+ * @param {string} value - type of notifiaction
+ * @return {React.Component} - Retrun all image beside notification body
+ */
+function NotificationImages({ image }) {
+  const
+    value = useContext(ReplayContext);
+  return (
+    <ImageContiner data-testid="notification-image">
+      { (value === 'commentReply' || value === 'postReply') ? (
+        <>
+          <NotificationImage src={image} alt="profile iamge" />
+          <ChildImage>
+            <ModeCommentIcon />
+          </ChildImage>
+        </>
+      ) : (value === 'userMention') ? (
+        <>
+          <NotificationImage src={image} alt="profile iamge" />
+          <ChildImage>
+            <PersonIcon />
+          </ChildImage>
+        </>
+      ) : (value === 'follow') ? (
+        <>
+          <NotificationImage src={image} alt="profile iamge" />
+          <ChildImage>
+            <FavoriteIcon />
+          </ChildImage>
+        </>
+      ) : (
+        <>
+          <NotificationImage src={image} alt="ring" />
+          <ChildImage>
+            { ' ' }
+            <NotificationsIcon />
+            { ' ' }
+          </ChildImage>
+        </>
+      ) }
+    </ImageContiner>
+  );
+}
+
+export default NotificationImages;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Notifications_NotificationsBody_NotificationsBody.jsx.html b/docs/components_Notifications_NotificationsBody_NotificationsBody.jsx.html new file mode 100644 index 00000000..1ad5f6e1 --- /dev/null +++ b/docs/components_Notifications_NotificationsBody_NotificationsBody.jsx.html @@ -0,0 +1,176 @@ + + + + + JSDoc: Source: components/Notifications/NotificationsBody/NotificationsBody.jsx + + + + + + + + + + +
+ +

Source: components/Notifications/NotificationsBody/NotificationsBody.jsx

+ + + + + + +
+
+
/* eslint-disable no-unused-vars */
+/* eslint-disable react/button-has-type */
+/* eslint-disable react/no-unstable-nested-components */
+/* eslint-disable react/jsx-no-constructed-context-values */
+/* eslint-disable import/no-cycle */
+import { createContext, useState, useEffect } from 'react';
+import { onForegroundNottification } from '../../../lib/firebase';
+import notificationsFetch, { notificationHide } from '../notificationsServer';
+import NotificationCategories from './NotificationCategories/NotificationCategories';
+import
+{
+  Notification, NotificationsContiner, NotificationsHead,
+} from './styles';
+
+export const CategoriesContext = createContext();
+
+/**
+ * - Notifications Body
+ * - fech notifications data from api
+ *  @component
+ *
+ * @property  {function} handleClick to set what notifiacation we select and it's type
+ * @property {function} handel deleteing when click hide
+ * @return {React.Component} - Body of each Notification depandent it's type
+ */
+
+function NotificationsBody({
+  setEarlier, setToday, earlier, today,
+}) {
+  // earlier data
+  // const [earlier, setEarlier] = useState([]);
+  // // today data
+  // const [today, setToday] = useState([]);
+  const [dataToday, dataEarlier] = notificationsFetch();
+  //  anchor element
+  const [anchorEl, setAnchorEl] = useState(null);
+  // index selected element
+  const [select, setSelect] = useState(null);
+  // type  selected element
+  const [type, setType] = useState(null);
+  // boll anchor element
+  const open = Boolean(anchorEl);
+
+  useEffect(() => {
+    setEarlier(dataEarlier);
+    setToday(dataToday);
+    console.log(dataToday);
+    console.log(dataEarlier);
+  }, [dataEarlier, dataToday]);
+  // function to set what notifiacation we select and it's type
+  const handleClick = (event, id) => {
+    event.stopPropagation();
+    console.log(id);
+    console.log(event);
+    setAnchorEl(event.currentTarget);
+    setSelect(id);
+    setType(event.currentTarget.getAttribute('catorige'));
+  };
+
+  useEffect(() => {
+    console.log('doaa');
+    onForegroundNottification()
+      .then((payload) => {
+        console.log('Received foreground message: ', payload);
+        const { data: { val } } = payload;
+        setToday((oldArray) => [JSON.parse(val), ...oldArray]);
+      })
+      .catch((err) => console.log('An error occured while retrieving foreground message. ', err));
+  });
+  // function to handel deleteing when click hide
+  const handleClose = (event) => {
+    event.stopPropagation();
+    console.log(select);
+    const tabindex = event.currentTarget.getAttribute('tabindex');
+    if (select !== null && tabindex === '0') {
+      if (type === 'today') {
+        setToday(
+          today.filter((e) => (e._id !== (select))),
+        );
+      } else {
+        setEarlier(
+          earlier.filter((e) => (e._id !== (select))),
+        );
+      }
+      notificationHide(select);
+      setSelect(null);
+    }
+    setAnchorEl(null);
+  };
+  return (
+    <Notification data-testid="notifications-body">
+      <NotificationsContiner>
+        { (today?.length !== 0)
+        && (
+        <>
+          <NotificationsHead>Today</NotificationsHead>
+
+          <CategoriesContext.Provider value={{
+            today, handleClose, handleClick, open, anchorEl,
+          }}
+          >
+            <NotificationCategories NavBar={false} />
+          </CategoriesContext.Provider>
+        </>
+        )}
+        { (earlier?.length !== 0)
+          && (
+          <>
+            {' '}
+            <NotificationsHead>Earlier</NotificationsHead>
+            <CategoriesContext.Provider value={{
+              earlier, handleClose, handleClick, open, anchorEl,
+            }}
+            >
+              <NotificationCategories NavBar={false} />
+            </CategoriesContext.Provider>
+          </>
+          )}
+      </NotificationsContiner>
+
+    </Notification>
+  );
+}
+
+export default NotificationsBody;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Notifications_notificationsServer.js.html b/docs/components_Notifications_notificationsServer.js.html new file mode 100644 index 00000000..212e030f --- /dev/null +++ b/docs/components_Notifications_notificationsServer.js.html @@ -0,0 +1,124 @@ + + + + + JSDoc: Source: components/Notifications/notificationsServer.js + + + + + + + + + + +
+ +

Source: components/Notifications/notificationsServer.js

+ + + + + + +
+
+
import { useState, useEffect } from 'react';
+import checkTimeNow from '../../utils/checkTimeNow';
+import axios from '../../services/instance';
+import { redirectLogin } from '../../utils/Redirect';
+/**
+ * - Notifications Fetch
+ */
+const notificationsFetch = () => {
+  // earlier data
+  const [earlier, setEarlier] = useState([]);
+  // today data
+  const [today, setToday] = useState([]);
+  const api = '/users/notifications';
+  useEffect(() => {
+    axios.get(api) // fetch api
+      .then((actualData) => {
+        console.log(actualData.data);
+        setToday(actualData.data.data.filter((e) => checkTimeNow(e.createdAt)));
+        setEarlier(actualData.data.data.filter((e) => !checkTimeNow(e.createdAt)));
+      })
+      .catch((error) => {
+        if (error.response.status === 401) {
+          window.location.href = './login';
+        }
+
+        console.log(error);
+      });
+  }, [api]);
+  return [today, earlier];
+};
+export default notificationsFetch;
+export const notificationMarkAll = async () => {
+  const api = '/users/notifications/mark_as_read';
+  await axios.patch(`${api}`)
+    .then((response) => {
+      console.log(response);
+    }).catch((error) => {
+      console.log(error);
+      if (error.message !== 'Network Error') {
+        if (error?.response.status === 401) {
+          redirectLogin();
+        }
+      }
+    });
+};
+export const notificationMarkRead = async (notificationId) => {
+  const api = `/users/notifications/${notificationId}/mark_as_read`;
+  await axios.patch(`${api}`)
+    .then((response) => {
+      console.log(response);
+    }).catch((error) => {
+      console.log(error);
+      if (error.message !== 'Network Error') {
+        if (error?.response.status === 401) {
+          redirectLogin();
+        }
+      }
+    });
+};
+export const notificationHide = async (notificationId) => {
+  const api = `/users/notifications/${notificationId}/hide`;
+  await axios.patch(`${api}`)
+    .then((response) => {
+      console.log(response);
+    }).catch((error) => {
+      console.log(error);
+      if (error.message !== 'Network Error') {
+        if (error?.response.status === 401) {
+          redirectLogin();
+        }
+      }
+    });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Popular_PopularContainer_PopularContainer.jsx.html b/docs/components_Popular_PopularContainer_PopularContainer.jsx.html new file mode 100644 index 00000000..3ddfeae6 --- /dev/null +++ b/docs/components_Popular_PopularContainer_PopularContainer.jsx.html @@ -0,0 +1,111 @@ + + + + + JSDoc: Source: components/Popular/PopularContainer/PopularContainer.jsx + + + + + + + + + + +
+ +

Source: components/Popular/PopularContainer/PopularContainer.jsx

+ + + + + + +
+
+
import { useMediaQuery, useTheme } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import MainContent from '../../MainContent/MainContent';
+import { MainContainer, OuterContainer } from '../../HomePage/HomePageContainer/styles';
+import SideBar from '../../SideBar/SideBar';
+import RedditPremium from '../../HomePage/HomePageContainer/RedditPremium/RedditPremium';
+import PersonalReddit from '../../HomePage/HomePageContainer/PersonalReddit/PersonalReddit';
+import HomePageFooter from '../../HomePage/HomePageContainer/HomePageFooter/HomePageFooter';
+import PostsClassification from '../../HomePage/HomePageContainer/PostsClassification/PostsClassification';
+import BackToTop from '../../BackToTop/BackToTop';
+import PostList from '../../HomePage/HomePageContainer/PostList/PostList';
+import popularPageServer from './popularPageServer';
+import { PopularPosts } from './styles';
+import cleanPage from '../../../utils/cleanPage';
+
+/**
+ * This component works as a container for all popular page components
+ * and a repository the data fetched in
+ *
+ * @component PopularContainer
+ * @returns {React.Component} Container represents the popular page
+ */
+function PopularContainer() {
+  const { postClass } = useParams();
+  // variables
+  const theme = useTheme();
+  const match = useMediaQuery(theme.breakpoints.up('md'));
+
+  // states
+  const [posts, postsError] = popularPageServer(postClass);
+  cleanPage();
+  return (
+    <OuterContainer>
+      <MainContainer>
+        <MainContent width={640}>
+          <PopularPosts>
+            Popular posts
+          </PopularPosts>
+          <PostsClassification allOrPopular="r/popular/" />
+          {!postsError ? (posts && <PostList posts={posts} />) : 'error in fetching posts'}
+        </MainContent>
+        {match
+        && (
+        <SideBar>
+          <RedditPremium />
+          <PersonalReddit
+            title="r/popular"
+            paragraph="The best posts on Reddit for you, pulled from the most active communities on Reddit. Check here to see the most shared, upvoted, and commented content on the internet."
+            image="https://www.redditstatic.com/desktop2x/img/id-cards/banner@2x.png"
+          />
+          <HomePageFooter />
+          <BackToTop />
+        </SideBar>
+        )}
+      </MainContainer>
+    </OuterContainer>
+  );
+}
+
+export default PopularContainer;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Post_Post.jsx.html b/docs/components_Post_Post.jsx.html new file mode 100644 index 00000000..38d8981c --- /dev/null +++ b/docs/components_Post_Post.jsx.html @@ -0,0 +1,311 @@ + + + + + JSDoc: Source: components/Post/Post.jsx + + + + + + + + + + +
+ +

Source: components/Post/Post.jsx

+ + + + + + +
+
+
/* eslint-disable react/no-danger */
+// mui components
+import {
+  Box, useMediaQuery, useTheme,
+} from '@mui/material';
+import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
+import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew';
+
+// styles
+import { useRef, useEffect, useState } from 'react';
+
+import { useNavigate } from 'react-router-dom';
+import {
+  PostContainer, PostMedia, CustomImage, PostText, PostTextContainer, ControlsIcon, PostUrl, PostUrlLink, LinkIcon,
+
+} from './styles';
+
+import Reactions from './Reactions/Reactions';
+import PostReactions from './PostReactions/PostReactions';
+import PostHeader from './PostHeader/PostHeader';
+import SharedPost from './SharedPost/SharedPost';
+/**
+ * This component is the view of the post in home page.
+ *
+ * @component Post
+ * @property {string} title -Post title.
+ * @property {string} ownerType -Post owner type user or subreddit.
+ * @property {string} ownerIcon -Post owner icon.
+ * @property {string} ownerName -Post subreddit(post owner).
+ * @property {string} authorName -Post author.
+ * @property {string} flairText -Post flair text.
+ * @property {string} flairBackgroundColor -Post flair background color.
+ * @property {string} flairColor -Post flair color.
+ * @property {string} kind -Post kind (link, self, image, video).
+ * @property {Array.<string>} images -Array of sources of images
+ * @property {Array.<string>} videos -Array of sources of vidoes
+ * @property {number} votes -Number of post votes.
+ * @property {number} commentCount -Number of post comments.
+ * @property {string} text -Post text in case of "self" kind.
+ * @property {boolean} subreddit -to identify if post in home page or subreddit.
+ * @property {number} postVoteStatus -The last vote of the current user in this post.
+ * @property {boolean} isSaved -Is this post saved by the current user or not.
+ * @property {number} postId -The Id of the current post.
+ * @property {string} url -The post url.
+ * @property {boolean} nsfw -Whether the post is not safe for work or not.
+ * @property {boolean} spoiler -Whether the post is spoiler or not.
+ * @property {Post} sharedFrom -the Parent post of the current one.
+ * @returns {React.Component} Post
+ */
+
+function Post(props) {
+  const {
+    createdAt, title, images, ownerType, ownerName, ownerIcon, authorName, flairText, flairBackgroundColor, flairColor, kind, votes, commentCount, text, video,
+    subredit, postVoteStatus, isSaved, postId, url, nsfw, spoiler, sharedFrom,
+  } = props;
+
+  // routes
+  const navigate = useNavigate();
+
+  // styles
+  const theme = useTheme();
+  const matchSm = useMediaQuery(theme.breakpoints.up('sm'));
+  const matchMd = useMediaQuery(theme.breakpoints.up('md'));
+
+  // variables
+  const maxTextHeight = 180;
+
+  // states
+  const [displayShadow, setDisplayShadow] = useState(false);
+  const [index, setIndex] = useState(0);
+  const [maxImagesHeight, setMaxImagesHeight] = useState(450);
+
+  // refs
+  const postTextRef = useRef();
+  const postMediaRef = useRef();
+
+  // handlers
+  const handleDirection = (dir) => {
+    setIndex(index + dir);
+  };
+
+  const redirectToPost = (redirect, shared) => {
+    if (redirect) {
+      const username = ownerName;
+      if (ownerType === 'User') {
+        if (username) {
+          navigate(`/user/${username}/comments/${shared ? sharedFrom?._id : postId}`);
+        } else {
+          navigate('/');
+        }
+      } else {
+        navigate(`/subreddit/${ownerName}/comments/${shared ? sharedFrom?._id : postId}`);
+      }
+    }
+  };
+
+  // effects
+  useEffect(() => {
+    setDisplayShadow(postTextRef?.current?.offsetHeight > maxTextHeight);
+  }, [text]);
+
+  useEffect(() => {
+    images?.forEach((image) => {
+      const img = new Image();
+
+      img.src = image;
+      img.onload = () => {
+        setMaxImagesHeight((maxImagesHeight) => {
+          const maxValue = Math.min(maxImagesHeight, img.height);
+          const postWidth = postMediaRef?.current?.offsetWidth;
+          if (maxImagesHeight > img.height && img.width > postWidth) {
+            return img.height * (postWidth / img.width);
+          }
+          return maxValue;
+        });
+      };
+    });
+  }, [images]);
+  if (sharedFrom) {
+    console.log('posty shared', props);
+  }
+
+  // console.log('for post ', postId, maxImagesHeight);
+  return (
+    <PostContainer my={2}>
+      {matchSm && (
+        <Reactions
+          flexDirection="column"
+          votes={votes}
+          postVoteStatus={postVoteStatus}
+          postId={postId}
+        />
+      )}
+      <Box
+        p={1}
+        flexGrow={1}
+        maxWidth={matchSm ? '94.5%' : '100%'}
+      >
+        <PostHeader
+          title={title}
+          ownerIcon={ownerIcon}
+          ownerName={ownerName}
+          authorName={authorName}
+          flairText={flairText}
+          flairBackgroundColor={flairBackgroundColor}
+          flairColor={flairColor}
+          createdAt={createdAt}
+          subredit={subredit}
+          ownerType={ownerType}
+          nsfw={nsfw}
+          spoiler={spoiler}
+          redirectToPost={redirectToPost}
+          sharedFrom={!!sharedFrom}
+        />
+        {/* eslint-disable jsx-a11y/media-has-caption */}
+        {/* */}
+        {!nsfw && (
+        <PostMedia
+          mt={1.5}
+          kind={kind}
+          ref={postMediaRef}
+          spoiler={spoiler}
+          onClick={() => redirectToPost(kind !== 'link', sharedFrom)}
+        >
+          {!sharedFrom ? (kind === 'video' ? (
+            <video controls style={{ width: '100%', maxHeight: '512px' }}>
+              <source src={video} type="video/mp4" />
+            </video>
+          ) : (
+            (kind === 'image')
+              ? (
+                <>
+                  {images.map((image, imageIndex) => (
+                    imageIndex === index
+                    && (
+                    <CustomImage
+                      src={image}
+                      alt="post image"
+                      key={image}
+                      maxHeight={maxImagesHeight}
+                    />
+                    )
+                  ))}
+                  <>
+                    <ControlsIcon
+                      disableRipple
+                      left={10}
+                      display={index <= 0 ? 'none' : 'flex'}
+                      sx={{
+                        boxShadow: 10,
+                      }}
+                      color="third"
+                      onClick={(e) => {
+                        e.stopPropagation();
+                        handleDirection(-1);
+                      }}
+                    >
+                      <ArrowBackIosNewIcon />
+                    </ControlsIcon>
+                    <ControlsIcon
+                      disableRipple
+                      right={10}
+                      display={index >= images.length - 1 ? 'none' : 'flex'}
+                      sx={{
+                        boxShadow: 10,
+                      }}
+                      color="third"
+                      onClick={(e) => {
+                        e.stopPropagation();
+                        handleDirection(1);
+                      }}
+                    >
+                      <ArrowForwardIosIcon />
+                    </ControlsIcon>
+                  </>
+                </>
+              ) : ((kind === 'self') ? (
+                <PostText
+                  ref={postTextRef}
+                  maxHeight={displayShadow ? maxTextHeight : 'none'}
+                >
+                  {displayShadow && <PostTextContainer />}
+                  <div dangerouslySetInnerHTML={{ __html: text }} />
+                </PostText>
+              )
+                : (
+                  <PostUrl href={url}>
+                    <PostUrlLink>
+                      {url}
+                    </PostUrlLink>
+                    <LinkIcon />
+                  </PostUrl>
+                ))
+          ))
+            : (
+              <SharedPost
+                sharedFrom={sharedFrom}
+                subredit={subredit}
+              />
+            )}
+        </PostMedia>
+        )}
+        <PostReactions
+          votes={votes}
+          matchSm={matchSm}
+          matchMd={matchMd}
+          comments={commentCount}
+          postVoteStatus={postVoteStatus}
+          isSaved={isSaved}
+          postId={sharedFrom?._id || postId}
+          redirectToPost={redirectToPost}
+          authorName={authorName}
+          subredit={subredit}
+        />
+      </Box>
+    </PostContainer>
+  );
+}
+
+export default Post;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Post_PostHeader_PostHeader.jsx.html b/docs/components_Post_PostHeader_PostHeader.jsx.html new file mode 100644 index 00000000..0bfdf592 --- /dev/null +++ b/docs/components_Post_PostHeader_PostHeader.jsx.html @@ -0,0 +1,196 @@ + + + + + JSDoc: Source: components/Post/PostHeader/PostHeader.jsx + + + + + + + + + + +
+ +

Source: components/Post/PostHeader/PostHeader.jsx

+ + + + + + +
+
+
// mui components
+import {
+  Avatar, Box, Typography,
+} from '@mui/material';
+import CallSplitIcon from '@mui/icons-material/CallSplit';
+import calculateTime from '../../../utils/calculateTime';
+
+// styles
+import {
+  CreatedAt,
+  Flair,
+  PostInfo, PostInfoLink, PostTitle, Tag,
+} from './styles';
+/**
+ * This component is the upper section of post
+ *
+ * @component PostHeader
+ * @property {string} title -Post title.
+ * @property {string} ownerType -Post owner type user or subreddit.
+ * @property {string} ownerIcon -Post ownerName icon.
+ * @property {string} ownerName -Post subreddit(post ownerName).
+ * @property {string} authorName -Post authorName.
+ * @property {string} flairText -Post flair text.
+ * @property {string} flairBackgroundColor -Post flair background color.
+ * @property {string} flairColor -Post flair color.
+ * @property {boolean} subredit -to identify if post in home page or subreddit.
+ * @property {boolean} nsfw -Whether the post is not safe for work or not.
+ * @property {boolean} spoiler -Whether the post is spoiler or not.
+ * @returns {React.Component} Post header
+ */
+
+function PostHeader(props) {
+  const {
+    title, ownerIcon, ownerType, ownerName, authorName, flairText, flairBackgroundColor, flairColor, createdAt,
+    subredit, nsfw, spoiler, redirectToPost, sharedFrom,
+  } = props;
+
+  const handleClickOnTitle = (e) => {
+    e.preventDefault();
+    redirectToPost(true, false);
+  };
+
+  return (
+    <>
+      <PostInfo pb={1}>
+        {!subredit
+        && (
+          <>
+            <Avatar
+              src={ownerIcon}
+              sx={{
+                width: 20,
+                height: 20,
+              }}
+              alt="Profile ownerIcon"
+            />
+            <PostInfoLink to={ownerType === 'Subreddit' ? `/r/${ownerName}` : `/user/${ownerName}`} color="#000" fontWeight="bolder">
+              {ownerType === 'Subreddit' ? 'r/' : 'u/'}
+              {ownerName}
+            </PostInfoLink>
+          </>
+        )}
+        <Box color="#787C7E" fontWeight={300} display="flex" gap="4px" flexWrap="wrap">
+          {ownerType === 'Subreddit' && (
+          <>
+            {!subredit && (
+            <span>
+              โ€ข
+            </span>
+            )}
+            {sharedFrom
+              ? (
+                <>
+                  <CallSplitIcon
+                    sx={{
+                      color: '#0079D3',
+                      transform: 'rotate(90deg)',
+                      width: 15,
+                      height: 15,
+                    }}
+                  />
+                  <div>Crossed By</div>
+                </>
+              )
+              : <div>Posted By</div>}
+            <PostInfoLink to={`/user/${authorName}`} color="inherit" fontWeight="normal">
+              u/
+              {authorName}
+            </PostInfoLink>
+          </>
+          )}
+
+          <CreatedAt color="inherit" fontWeight="normal">
+            {calculateTime(createdAt)}
+          </CreatedAt>
+        </Box>
+      </PostInfo>
+      <PostTitle onClick={handleClickOnTitle}>
+        <Typography
+          variant="h6"
+          component="h3"
+          sx={{ fontSize: 18 }}
+        >
+          {title}
+          {' '}
+          {
+            flairText
+            && (
+            <Flair
+              disableRipple
+              backgroundColor={flairBackgroundColor}
+              flairColor={flairColor}
+            >
+              {flairText}
+            </Flair>
+            )
+          }
+          {' '}
+          {
+            spoiler && (
+            <Tag
+              color="third"
+              variant="outlined"
+            >
+              spoiler
+            </Tag>
+            )
+          }
+          {
+            nsfw && (
+            <Tag
+              color="nsfw"
+              variant="outlined"
+            >
+              nsfw
+            </Tag>
+            )
+          }
+        </Typography>
+      </PostTitle>
+    </>
+  );
+}
+
+export default PostHeader;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Post_PostReactions_PostReactions.jsx.html b/docs/components_Post_PostReactions_PostReactions.jsx.html new file mode 100644 index 00000000..7f93ddcb --- /dev/null +++ b/docs/components_Post_PostReactions_PostReactions.jsx.html @@ -0,0 +1,296 @@ + + + + + JSDoc: Source: components/Post/PostReactions/PostReactions.jsx + + + + + + + + + + +
+ +

Source: components/Post/PostReactions/PostReactions.jsx

+ + + + + + +
+
+
import { useState } from 'react';
+// icons
+import ModeEditOutlineOutlinedIcon from '@mui/icons-material/ModeEditOutlineOutlined';
+import ChatBubbleOutlineRoundedIcon from '@mui/icons-material/ChatBubbleOutlineRounded';
+import MoreHorizOutlinedIcon from '@mui/icons-material/MoreHorizOutlined';
+import ShareOutlinedIcon from '@mui/icons-material/ShareOutlined';
+import BookmarkBorderIcon from '@mui/icons-material/BookmarkBorder';
+import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
+import FlagOutlinedIcon from '@mui/icons-material/FlagOutlined';
+import BookmarksOutlinedIcon from '@mui/icons-material/BookmarksOutlined';
+import DeleteOutlineOutlinedIcon from '@mui/icons-material/DeleteOutlineOutlined';
+
+// mui components
+import {
+  Box, ClickAwayListener, Divider, IconButton, ListItemButton, ListItemIcon, useMediaQuery,
+} from '@mui/material';
+
+// styles
+import { useTheme } from '@mui/system';
+import { useNavigate, useParams } from 'react-router-dom';
+import { useEditPostContext } from '../../../contexts/EditPostContext';
+import {
+  PostActions, ActionButton, ShowMoreList, ShowMoreListItemText,
+} from './styles';
+import Reactions from '../Reactions/Reactions';
+import postReactionsServer from '../postReactionsServer';
+import { useHiddenPostsContext } from '../../../contexts/HiddenPostsContext';
+import UserLogin from '../../../authentication';
+
+/**
+ * This component is the container of post reactions
+ *
+ * @component PostReactions
+ * @property {number} votes -Number of post votes.
+ * @property {boolean} matchMd -check whether screen size is larger than meduim
+ * @property {boolean} matchSm -check whether screen size is larger than small
+ * @property {number} commentCount -Number of post comments.
+ * @property {number} postVoteStatus -The last vote of the current user in this post.
+ * @property {boolean} isSaved -Is this post saved by the current user or not.
+ * @property {number} postId -The Id of the current post.
+ * @returns {React.Component}  All post reactions.
+ */
+
+function PostReactions(props) {
+  const {
+    matchSm, comments, matchMd, votes, postVoteStatus, isSaved, postId, redirectToPost, authorName, subredit,
+  } = props;
+
+  const [showMore, setShowMore] = useState(false);
+  const [save, setSave] = useState(isSaved);
+  const theme = useTheme();
+  const matchXs = useMediaQuery(theme.breakpoints.down('xs'));
+  const matchXxs = useMediaQuery(theme.breakpoints.down('xxs'));
+  const { setHiddenPosts } = useHiddenPostsContext();
+
+  // routes
+  const navigate = useNavigate();
+  const { Name } = useParams();
+
+  // handlers
+  const handleShowMore = () => {
+    setShowMore(!showMore);
+  };
+  const handleSave = () => {
+    postReactionsServer(postId, save ? 'unsave' : 'save', save);
+    setSave(!save);
+  };
+  const handleClickAway = () => setShowMore(false);
+  const handleHide = () => {
+    setHiddenPosts((hiddenPosts) => [...hiddenPosts, postId]);
+    postReactionsServer(postId, 'hide', 1, setHiddenPosts);
+  };
+
+  const handleDelete = () => {
+    setHiddenPosts((hiddenPosts) => [...hiddenPosts, postId]);
+    postReactionsServer(postId, 'delete', 1, setHiddenPosts);
+  };
+
+  const handleShare = () => {
+    if (!subredit) {
+      navigate(`/submit/${postId}`);
+    } else {
+      navigate(`/submit/${postId}/r/${Name}`);
+    }
+  };
+  // contexts
+  const { setEditPost, setCommentPost } = useEditPostContext();
+
+  // variables
+  const isMe = UserLogin([authorName]);
+  return (
+    <PostActions mt={0.5}>
+      {!matchSm && (
+      <Reactions
+        flexDirection="row"
+        postVoteStatus={postVoteStatus}
+        votes={votes}
+        postId={postId}
+      />
+      )}
+      <ActionButton
+        color="third"
+        startIcon={<ChatBubbleOutlineRoundedIcon />}
+        onClick={() => {
+          setCommentPost(true);
+          setEditPost(false);
+          redirectToPost(true);
+        }}
+      >
+        {comments}
+        {' '}
+        comments
+      </ActionButton>
+      {!matchXs
+      && (
+      <ActionButton
+        color="third"
+        startIcon={<ShareOutlinedIcon />}
+        onClick={handleShare}
+      >
+        Share
+
+      </ActionButton>
+      )}
+      {matchMd && (
+      <ActionButton
+        color="third"
+        startIcon={save
+          ? (
+            <BookmarksOutlinedIcon />
+          ) : (
+            <BookmarkBorderIcon
+              sx={{
+                width: '25px !important',
+                height: '25px !important',
+              }}
+            />
+
+          )}
+        onClick={handleSave}
+        data-testid="save button"
+      >
+        {save ? 'Unsave' : 'Save'}
+      </ActionButton>
+      )}
+      <ClickAwayListener onClickAway={handleClickAway}>
+        <Box position="relative" display="flex">
+          <IconButton
+            sx={{
+              borderRadius: '10%',
+              py: 0.4,
+            }}
+            onClick={handleShowMore}
+            color="third"
+          >
+            <MoreHorizOutlinedIcon />
+          </IconButton>
+
+          <ShowMoreList
+            sx={{ boxShadow: 2 }}
+            display={(showMore === false ? 'none' : 'block')}
+            match={matchXxs}
+          >
+            {matchXs && (
+            <>
+              <ListItemButton onClick={handleSave}>
+                <ListItemIcon>
+                  <ShareOutlinedIcon />
+                </ListItemIcon>
+                <ShowMoreListItemText>
+                  Share
+                </ShowMoreListItemText>
+              </ListItemButton>
+              <Divider />
+            </>
+            )}
+            {!matchMd && (
+            <>
+              <ListItemButton onClick={handleSave}>
+                <ListItemIcon>
+                  {save ? <BookmarksOutlinedIcon /> : <BookmarkBorderIcon />}
+                </ListItemIcon>
+                <ShowMoreListItemText>
+                  {save ? 'Unsave' : 'Save'}
+                </ShowMoreListItemText>
+              </ListItemButton>
+              <Divider />
+            </>
+            )}
+            {isMe && (
+            <>
+              <ListItemButton onClick={() => {
+                setEditPost(true);
+                setCommentPost(false);
+                redirectToPost(true);
+              }}
+              >
+                <ListItemIcon>
+                  <ModeEditOutlineOutlinedIcon />
+                </ListItemIcon>
+                <ShowMoreListItemText>
+                  edit post
+                </ShowMoreListItemText>
+              </ListItemButton>
+              <Divider />
+            </>
+            )}
+            <ListItemButton onClick={handleHide}>
+              <ListItemIcon>
+                <VisibilityOffOutlinedIcon />
+              </ListItemIcon>
+              <ShowMoreListItemText>
+                hide
+              </ShowMoreListItemText>
+            </ListItemButton>
+            <Divider />
+            {isMe && (
+            <>
+              <ListItemButton onClick={handleDelete}>
+                <ListItemIcon>
+                  <DeleteOutlineOutlinedIcon />
+                </ListItemIcon>
+                <ShowMoreListItemText>
+                  delete
+                </ShowMoreListItemText>
+              </ListItemButton>
+              <Divider />
+            </>
+            )}
+            <ListItemButton>
+              <ListItemIcon>
+                <FlagOutlinedIcon />
+              </ListItemIcon>
+              <ShowMoreListItemText>
+                report
+              </ShowMoreListItemText>
+            </ListItemButton>
+          </ShowMoreList>
+        </Box>
+      </ClickAwayListener>
+    </PostActions>
+  );
+}
+
+export default PostReactions;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Post_Reactions_Reactions.jsx.html b/docs/components_Post_Reactions_Reactions.jsx.html new file mode 100644 index 00000000..f12b4985 --- /dev/null +++ b/docs/components_Post_Reactions_Reactions.jsx.html @@ -0,0 +1,153 @@ + + + + + JSDoc: Source: components/Post/Reactions/Reactions.jsx + + + + + + + + + + +
+ +

Source: components/Post/Reactions/Reactions.jsx

+ + + + + + +
+
+
import { useTheme } from '@mui/system';
+import { useReducer } from 'react';
+import millify from 'millify';
+import { ReactionIconButton, Votes, Voting } from './styles';
+import VoteIcon from '../../VoteIcons/VoteIcon/VoteIcon';
+import VotedIcon from '../../VoteIcons/VotedIcon/VotedIcon';
+import postReactionsServer from '../postReactionsServer';
+/**
+ * This component is the container of reactions
+ *
+ * @component Reactions
+ * @property {string} flexDirection -The direction of reactions (vertical or horizontal).
+ * @property {number} votes -Number of post votes.
+ * @property {number} postId -The Id of the current post.
+ * @property {boolean} viewpost -To differentiate between post and view post.
+ * @returns {React.Component}  Upvote and downvote only.
+ */
+
+function Reactions(props) {
+  const {
+    flexDirection, votes, postVoteStatus, postId, viewpost,
+  } = props;
+  // console.log('vote status', postVoteStatus, postId);
+  const theme = useTheme();
+  const reducer = (state, action) => {
+    switch (action) {
+      case 'upvote':
+        postReactionsServer(postId, 'vote', 1);
+        return 1;
+      case 'downvote':
+        postReactionsServer(postId, 'vote', -1);
+        return -1;
+      default:
+        postReactionsServer(postId, 'vote', 0);
+        return 0;
+    }
+  };
+  const [reaction, dispatch] = useReducer(reducer, postVoteStatus);
+  return (
+    <Voting
+      flexDirection={flexDirection}
+      gap={0.5}
+      viewpost={viewpost}
+    >
+      {(reaction === 1)
+        ? (
+          <ReactionIconButton
+            onClick={() => dispatch('cancel upvote')}
+            data-testid="upvoted button"
+          >
+            <VotedIcon
+              color={theme.palette.secondary?.main}
+              direction="up"
+            />
+          </ReactionIconButton>
+        )
+        : (
+          <ReactionIconButton
+            onClick={() => dispatch('upvote')}
+            data-testid="upvote button"
+          >
+            <VoteIcon
+              color={theme.palette.secondary?.main}
+              direction="up"
+            />
+          </ReactionIconButton>
+        )}
+      <Votes color={(reaction === 0 ? '#000' : (reaction === 1 ? theme.palette.secondary?.main : theme.palette.primary?.main))}>
+        {millify(votes + reaction - postVoteStatus, {
+          units: ['', 'k', 'm', 'b'],
+          precision: 1,
+        })}
+      </Votes>
+      {(reaction === -1)
+        ? (
+          <ReactionIconButton
+            onClick={() => dispatch('cancel downvote')}
+            data-testid="downvoted button"
+          >
+            <VotedIcon
+              color={theme.palette.primary?.main}
+              direction="down"
+            />
+          </ReactionIconButton>
+        )
+        : (
+          <ReactionIconButton
+            onClick={() => dispatch('downvote')}
+            data-testid="downvote button"
+          >
+            <VoteIcon
+              color={theme.palette.primary?.main}
+              direction="down"
+              data-testid="downvote"
+            />
+          </ReactionIconButton>
+        )}
+    </Voting>
+  );
+}
+
+export default Reactions;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Post_SharedPost_PostHeader_PostHeader.jsx.html b/docs/components_Post_SharedPost_PostHeader_PostHeader.jsx.html new file mode 100644 index 00000000..0809081c --- /dev/null +++ b/docs/components_Post_SharedPost_PostHeader_PostHeader.jsx.html @@ -0,0 +1,170 @@ + + + + + JSDoc: Source: components/Post/SharedPost/PostHeader/PostHeader.jsx + + + + + + + + + + +
+ +

Source: components/Post/SharedPost/PostHeader/PostHeader.jsx

+ + + + + + +
+
+
// mui components
+import {
+  Box, Typography,
+} from '@mui/material';
+import calculateTime from '../../../../utils/calculateTime';
+// styles
+import {
+  CreatedAt,
+  Flair,
+  PostInfo, PostInfoLink, PostTitle, Tag,
+} from './styles';
+/**
+ * This component is the upper section of post
+ *
+ * @component PostHeader
+ * @property {string} title -Post title.
+ * @property {string} ownerType -Post owner type user or subreddit.
+ * @property {string} ownerName -Post subreddit(post ownerName).
+ * @property {string} authorName -Post authorName.
+ * @property {string} flairText -Post flair text.
+ * @property {string} flairBackgroundColor -Post flair background color.
+ * @property {string} flairColor -Post flair color.
+ * @property {boolean} subredit -to identify if post in home page or subreddit.
+ * @property {boolean} nsfw -Whether the post is not safe for work or not.
+ * @property {boolean} spoiler -Whether the post is spoiler or not.
+ * @returns {React.Component} Post header
+ */
+
+function PostHeader(props) {
+  const {
+    title, ownerType, ownerName, authorName, flairText, flairBackgroundColor, flairColor, createdAt,
+    subredit, nsfw, spoiler, redirectToPost,
+
+  } = props;
+
+  const handleClickOnTitle = (e) => {
+    e.preventDefault();
+    redirectToPost(true);
+  };
+
+  return (
+    <>
+      <PostInfo pb={1}>
+        {!subredit
+        && (
+          <PostInfoLink to={ownerType === 'Subreddit' ? `/r/${ownerName}` : `/user/${ownerName}`} color="#000" fontWeight="bolder">
+              {ownerType === 'Subreddit' ? 'r/' : 'u/'}
+              {ownerName}
+          </PostInfoLink>
+        )}
+        <Box color="#787C7E" fontWeight={300} display="flex" gap="4px" flexWrap="wrap">
+          {ownerType === 'Subreddit' && (
+          <>
+            {!subredit && (
+            <span>
+              โ€ข
+            </span>
+            )}
+            <div>Posted By</div>
+            <PostInfoLink to={`/user/${authorName}`} color="inherit" fontWeight="normal">
+              u/
+              {authorName}
+            </PostInfoLink>
+          </>
+          )}
+
+          <CreatedAt color="inherit" fontWeight="normal">
+            {calculateTime(createdAt)}
+          </CreatedAt>
+        </Box>
+      </PostInfo>
+      <PostTitle onClick={handleClickOnTitle}>
+        <Typography
+          variant="h6"
+          component="h3"
+          sx={{ fontSize: 18 }}
+        >
+          {title}
+          {' '}
+          {
+            flairText
+            && (
+            <Flair
+              disableRipple
+              backgroundColor={flairBackgroundColor}
+              flairColor={flairColor}
+            >
+              {flairText}
+            </Flair>
+            )
+          }
+          {' '}
+          {
+            spoiler && (
+            <Tag
+              color="third"
+              variant="outlined"
+            >
+              spoiler
+            </Tag>
+            )
+          }
+          {
+            nsfw && (
+            <Tag
+              color="nsfw"
+              variant="outlined"
+            >
+              nsfw
+            </Tag>
+            )
+          }
+        </Typography>
+      </PostTitle>
+    </>
+  );
+}
+
+export default PostHeader;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Post_SharedPost_SharedPost.jsx.html b/docs/components_Post_SharedPost_SharedPost.jsx.html new file mode 100644 index 00000000..8aadf889 --- /dev/null +++ b/docs/components_Post_SharedPost_SharedPost.jsx.html @@ -0,0 +1,294 @@ + + + + + JSDoc: Source: components/Post/SharedPost/SharedPost.jsx + + + + + + + + + + +
+ +

Source: components/Post/SharedPost/SharedPost.jsx

+ + + + + + +
+
+
/* eslint-disable react/no-danger */
+// mui components
+import {
+  Box, useMediaQuery, useTheme,
+} from '@mui/material';
+import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
+import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew';
+
+// styles
+import { useRef, useEffect, useState } from 'react';
+
+import { useNavigate } from 'react-router-dom';
+import {
+  PostContainer, PostMedia, CustomImage, PostText, PostTextContainer, ControlsIcon, PostUrl, PostUrlLink, LinkIcon,
+
+} from './styles';
+
+import PostHeader from './PostHeader/PostHeader';
+/**
+ * This component is the view of the post in home page.
+ *
+ * @component Post
+ * @property {string} title -Post title.
+ * @property {string} ownerType -Post owner type user or subreddit.
+ * @property {string} ownerIcon -Post owner icon.
+ * @property {string} ownerName -Post subreddit(post owner).
+ * @property {string} authorName -Post author.
+ * @property {string} flairText -Post flair text.
+ * @property {string} flairBackgroundColor -Post flair background color.
+ * @property {string} flairColor -Post flair color.
+ * @property {string} kind -Post kind (link, self, image, video).
+ * @property {Array.<string>} images -Array of sources of images
+ * @property {Array.<string>} videos -Array of sources of vidoes
+ * @property {number} votes -Number of post votes.
+ * @property {number} commentCount -Number of post comments.
+ * @property {string} text -Post text in case of "self" kind.
+ * @property {boolean} subreddit -to identify if post in home page or subreddit.
+ * @property {number} postVoteStatus -The last vote of the current user in this post.
+ * @property {boolean} isSaved -Is this post saved by the current user or not.
+ * @property {number} postId -The Id of the current post.
+ * @property {string} url -The post url.
+ * @property {boolean} nsfw -Whether the post is not safe for work or not.
+ * @property {boolean} spoiler -Whether the post is spoiler or not.
+ * @returns {React.Component} Post
+ */
+
+function Post(props) {
+  const { sharedFrom, subredit } = props;
+  const temp = {
+    _id: 1,
+    text: '',
+    backgroundColor: '',
+    textColor: '',
+  };
+  const {
+    text: flairText,
+    backgroundColor: flairBackgroundColor,
+    textColor: flairColor,
+  } = (sharedFrom?.flairId) || temp;
+  const { name: ownerName, icon: ownerIcon } = sharedFrom?.owner || {};
+  const { name: authorName } = sharedFrom?.author || {};
+
+  console.log('sharedfrom', sharedFrom);
+  const {
+    _id: postId, createdAt, title, images, kind, text, video, ownerType, url, nsfw, spoiler,
+  } = sharedFrom;
+
+  console.log('wow', {
+    _id: postId, createdAt, title, images, ownerName, ownerIcon, authorName, flairText, flairBackgroundColor, flairColor, kind, text, video, ownerType, url, nsfw, spoiler,
+  });
+  // routes
+  const navigate = useNavigate();
+
+  // styles
+  const theme = useTheme();
+  const matchSm = useMediaQuery(theme.breakpoints.up('sm'));
+
+  // variables
+  const maxTextHeight = 180;
+
+  // states
+  const [displayShadow, setDisplayShadow] = useState(false);
+  const [index, setIndex] = useState(0);
+  const [maxImagesHeight, setMaxImagesHeight] = useState(450);
+
+  // refs
+  const postTextRef = useRef();
+  const postMediaRef = useRef();
+
+  // handlers
+  const handleDirection = (dir) => {
+    setIndex(index + dir);
+  };
+
+  const redirectToPost = (redirect) => {
+    if (redirect) {
+      const username = ownerName;
+      if (ownerType === 'User') {
+        if (username) {
+          navigate(`/user/${username}/comments/${postId}`);
+        } else {
+          navigate('/');
+        }
+      } else {
+        navigate(`/r/${ownerName}/comments/${postId}`);
+      }
+    }
+  };
+
+  // effects
+  useEffect(() => {
+    setDisplayShadow(postTextRef?.current?.offsetHeight > maxTextHeight);
+  }, [text]);
+
+  useEffect(() => {
+    images?.forEach((image) => {
+      const img = new Image();
+
+      img.src = image;
+      img.onload = () => {
+        setMaxImagesHeight((maxImagesHeight) => {
+          const maxValue = Math.min(maxImagesHeight, img.height);
+          const postWidth = postMediaRef?.current?.offsetWidth;
+          if (maxImagesHeight > img.height && img.width > postWidth) {
+            return img.height * (postWidth / img.width);
+          }
+          return maxValue;
+        });
+      };
+    });
+  }, [images]);
+
+  // console.log('for post ', postId, maxImagesHeight);
+  return (
+    <PostContainer>
+      <Box
+        p={1}
+        flexGrow={1}
+        maxWidth={matchSm ? '94.5%' : '100%'}
+      >
+        <PostHeader
+          title={title}
+          ownerIcon={ownerIcon}
+          ownerName={ownerName}
+          authorName={authorName}
+          flairText={flairText}
+          flairBackgroundColor={flairBackgroundColor}
+          flairColor={flairColor}
+          createdAt={createdAt}
+          subredit={subredit}
+          ownerType={ownerType}
+          nsfw={nsfw}
+          spoiler={spoiler}
+          redirectToPost={redirectToPost}
+        />
+        {/* eslint-disable jsx-a11y/media-has-caption */}
+        {/* */}
+        {!nsfw && (
+        <PostMedia
+          mt={1.5}
+          kind={kind}
+          ref={postMediaRef}
+          spoiler={spoiler}
+          onClick={() => redirectToPost(kind !== 'link')}
+        >
+          {kind === 'video' ? (
+            <video controls style={{ width: '100%', maxHeight: '512px' }}>
+              <source src={video} type="video/mp4" />
+            </video>
+          ) : (
+            (kind === 'image')
+              ? (
+                <>
+                  {images.map((image, imageIndex) => (
+                    imageIndex === index
+                    && (
+                    <CustomImage
+                      src={image}
+                      alt="post image"
+                      key={image}
+                      maxHeight={maxImagesHeight}
+                    />
+                    )
+                  ))}
+                  <>
+                    <ControlsIcon
+                      disableRipple
+                      left={10}
+                      display={index <= 0 ? 'none' : 'flex'}
+                      sx={{
+                        boxShadow: 10,
+                      }}
+                      color="third"
+                      onClick={(e) => {
+                        e.stopPropagation();
+                        handleDirection(-1);
+                      }}
+                    >
+                      <ArrowBackIosNewIcon />
+                    </ControlsIcon>
+                    <ControlsIcon
+                      disableRipple
+                      right={10}
+                      display={index >= images.length - 1 ? 'none' : 'flex'}
+                      sx={{
+                        boxShadow: 10,
+                      }}
+                      color="third"
+                      onClick={(e) => {
+                        e.stopPropagation();
+                        handleDirection(1);
+                      }}
+                    >
+                      <ArrowForwardIosIcon />
+                    </ControlsIcon>
+                  </>
+                </>
+              ) : ((kind === 'self') ? (
+                <PostText
+                  ref={postTextRef}
+                  maxHeight={displayShadow ? maxTextHeight : 'none'}
+                >
+                  {displayShadow && <PostTextContainer />}
+                  <div dangerouslySetInnerHTML={{ __html: text }} />
+                </PostText>
+              )
+                : (
+                  <PostUrl href={url}>
+                    <PostUrlLink>
+                      {url}
+                    </PostUrlLink>
+                    <LinkIcon />
+                  </PostUrl>
+                ))
+          )}
+        </PostMedia>
+        )}
+      </Box>
+    </PostContainer>
+  );
+}
+
+export default Post;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_Comments_Comments.jsx.html b/docs/components_Search_Comments_Comments.jsx.html new file mode 100644 index 00000000..572b25e3 --- /dev/null +++ b/docs/components_Search_Comments_Comments.jsx.html @@ -0,0 +1,193 @@ + + + + + JSDoc: Source: components/Search/Comments/Comments.jsx + + + + + + + + + + +
+ +

Source: components/Search/Comments/Comments.jsx

+ + + + + + +
+
+
import {
+  Avatar, Box, Typography,
+} from '@mui/material';
+import calculateTime from '../../../utils/calculateTime';
+import numFormatter from '../../../utils/MembersNum';
+import {
+  PostContainer, PostInfo, PostInfoLink, PostTitle,
+  PostRich,
+  CommentContainer,
+  CommentReach,
+  GoToThread,
+  PostLink,
+} from './style';
+
+/**
+ * Search by Comments entity
+ * @component
+ * @return {React.Component} - Search by community entity
+ */
+function Comments(props) {
+  const { Comment } = props;
+  return (
+    <PostContainer sx={{ '&:hover': { border: 1 } }}>
+      <Box width="100%">
+        <Box sx={{ padding: '16px 16px 4px' }}>
+          <PostInfo>
+            <Avatar
+              src={Comment.post.owner.icon}
+              sx={{
+                width: 20,
+                height: 20,
+              }}
+              alt="Profile Image"
+            />
+            <PostInfoLink to={`/r/${Comment.post.owner.fixedName}`} color="#000" fontWeight="bolder">
+              r/
+              {Comment.post.owner.name}
+            </PostInfoLink>
+            <Box color="#787C7E" fontWeight={300} display="flex" gap="4px" flexWrap="wrap">
+              <span>
+                โ€ข
+              </span>
+              <div>Posted By</div>
+              <Avatar
+                src={Comment.post.author.profilePicture}
+                sx={{
+                  width: 20,
+                  height: 20,
+                }}
+                alt="Profile Image"
+              />
+              <PostInfoLink to={`/user/${Comment.post.author.userName}`} color="inherit" fontWeight="normal">
+                u/
+                {Comment.post.author.displayName}
+                {' '}
+                {calculateTime(Comment.post.createdAt)}
+              </PostInfoLink>
+            </Box>
+          </PostInfo>
+        </Box>
+
+        <PostTitle>
+          <PostLink to={`../subreddit/${Comment.post?.owner?.fixedName}/comments/${Comment.post?._id}`}>
+            <Typography
+              variant="h6"
+              component="h3"
+              sx={{
+                fontSize: 12, marginBottom: '12px', fontWeight: '400',
+              }}
+            >
+              {Comment.post.title.replace(/<[^>]+>/g, '')}
+            </Typography>
+          </PostLink>
+          <CommentContainer to={`../subreddit/${Comment.post?.owner?.fixedName}/comments/${Comment.post?._id}/${Comment?._id}`}>
+            <Avatar
+              src={Comment.author.profilePicture}
+              sx={{
+                width: 20,
+                height: 20,
+                margin: 1,
+              }}
+              alt="Profile Image"
+            />
+            <Box>
+              <PostInfo py={1}>
+
+                <PostInfoLink to={`/user/${Comment.author.userName}`} color="#000" fontWeight="bolder">
+                  {Comment.author.displayName}
+                </PostInfoLink>
+                <Box color="#787C7E" fontWeight={300} display="flex" gap="4px" flexWrap="wrap">
+                  <Typography component="span" mx="4px" sx={{ fontSize: '6px', display: 'flex', alignItems: 'center' }}>
+                    โ€ข
+                  </Typography>
+                  <PostInfoLink to="/" color="inherit" fontWeight="normal">
+                    {calculateTime(Comment.createdAt)}
+                  </PostInfoLink>
+                </Box>
+              </PostInfo>
+              {/* question */}
+              <Typography variant="h6" component="h3" sx={{ fontSize: 14, marginBottom: '12px', fontWeight: '400' }}>
+                {Comment.text.replace(/<[^>]+>/g, '')}
+              </Typography>
+              <CommentReach>
+                <Typography variant="span" sx={{ marginRight: 3, padding: 0 }}>
+                  {numFormatter(Comment.votes)}
+                  {' '}
+                  upvotes
+                  {' '}
+                </Typography>
+                <Typography variant="span" sx={{ marginRight: 3, padding: 0 }}>
+                  {numFormatter(Comment.Comment)}
+                  {' '}
+                  awards
+                  {' '}
+                </Typography>
+              </CommentReach>
+            </Box>
+          </CommentContainer>
+        </PostTitle>
+        <GoToThread to={`../subreddit/${Comment.post?.owner?.fixedName}/comments/${Comment.post?._id}/${Comment?._id}`}>
+          Go to thread
+        </GoToThread>
+        <PostRich mt={5}>
+          <Typography variant="span" sx={{ marginRight: 3 }}>
+            {numFormatter(Comment.post.votes)}
+            {' '}
+            upvotes
+            {' '}
+          </Typography>
+          <Typography variant="span" sx={{ marginRight: 3 }}>
+            {numFormatter(Comment.post.commentCount)}
+            {' '}
+            comments
+            {' '}
+          </Typography>
+        </PostRich>
+      </Box>
+    </PostContainer>
+  );
+}
+
+export default Comments;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_Header_Filter.jsx.html b/docs/components_Search_Header_Filter.jsx.html new file mode 100644 index 00000000..5cec613a --- /dev/null +++ b/docs/components_Search_Header_Filter.jsx.html @@ -0,0 +1,113 @@ + + + + + JSDoc: Source: components/Search/Header/Filter.jsx + + + + + + + + + + +
+ +

Source: components/Search/Header/Filter.jsx

+ + + + + + +
+
+
import { useNavigate, useSearchParams } from 'react-router-dom';
+
+import {
+  Header, HeaderContainer, MyCategory,
+} from './style';
+
+/**
+ * filter Search by its type
+ *
+ * @component FilterSearch
+ * @property  {function} handleClick navigate
+
+ * @returns {React.Component} filter Search by its type
+ */
+function FilterSearch() {
+  const [searchParams] = useSearchParams();
+
+  const type1 = searchParams.get('type') || 'posts';
+  const type = type1.toLowerCase();
+
+  const qery = searchParams.get('q');
+
+  const navigate = useNavigate();
+
+  // navigate
+  const handleClick = (subPage) => {
+    navigate(`?q=${qery}&type=${subPage}`);
+  };
+
+  return (
+    <HeaderContainer>
+      <Header>
+        <MyCategory
+          condition={(type === 'posts').toString()}
+          onClick={() => { handleClick('posts'); console.log((type === 'posts').toString()); }}
+        >
+          Posts
+        </MyCategory>
+        <MyCategory
+          condition={(type === 'comments').toString()}
+          onClick={() => { handleClick('comments'); }}
+        >
+          Comments
+        </MyCategory>
+        <MyCategory
+          condition={(type === 'communities').toString()}
+          onClick={() => { handleClick('communities'); }}
+        >
+          Communities
+        </MyCategory>
+        <MyCategory
+          condition={(type === 'people').toString()}
+          onClick={() => { handleClick('people'); }}
+        >
+          People
+        </MyCategory>
+      </Header>
+    </HeaderContainer>
+  );
+}
+
+export default FilterSearch;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_Peoples_FollowServer.js.html b/docs/components_Search_Peoples_FollowServer.js.html new file mode 100644 index 00000000..f971fecd --- /dev/null +++ b/docs/components_Search_Peoples_FollowServer.js.html @@ -0,0 +1,106 @@ + + + + + JSDoc: Source: components/Search/Peoples/FollowServer.js + + + + + + + + + + +
+ +

Source: components/Search/Peoples/FollowServer.js

+ + + + + + +
+
+
// import { useEffect, useState } from 'react';
+// import axios from '../../../services/instance';
+// /**
+//  * Follow
+//  *
+//  * @property {string} username - username to send
+//  * @property {boolean} isFollowed - name for rule
+
+//  */
+// export const followRequest = (username, isFollowed) => {
+//   const [data, setData] = useState(null);
+
+//   useEffect(() => {
+//     if (isFollowed === undefined) {
+//       console.log('undefined');
+//       return;
+//     }
+//     axios.post(`users/${username}/${isFollowed ? 'follow' : 'unfollow'}`, {
+
+//     }).then((response) => {
+//       if (response.status === 401) {
+//         window.location.pathname = 'login';
+//       }
+//       setData(response.data);
+//     }).catch((error) => {
+//       console.log(error);
+//     });
+//   }, [username, isFollowed]);
+//   return [data];
+// };
+
+import Done from '../../AlertMessage';
+import axios from '../../../services/instance';
+/**
+  * Follow
+  *
+  * @property {string} username - username to send
+  * @property {boolean} isFollowed - name for rule
+
+ */
+const followRequest = async (username, isFollowed) => {
+  axios.post(`users/${username}/${isFollowed ? 'follow' : 'unfollow'}`, {
+
+  }).then((response) => {
+    if (response.status === 401) {
+      window.location.pathname = 'login';
+    }
+    if (response.status === 200 || response.status === 204) {
+      Done('Done');
+    }
+  }).catch((error) => {
+    console.log(error);
+  });
+};
+export default followRequest;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_Peoples_People.jsx.html b/docs/components_Search_Peoples_People.jsx.html new file mode 100644 index 00000000..2eaa69c1 --- /dev/null +++ b/docs/components_Search_Peoples_People.jsx.html @@ -0,0 +1,125 @@ + + + + + JSDoc: Source: components/Search/Peoples/People.jsx + + + + + + + + + + +
+ +

Source: components/Search/Peoples/People.jsx

+ + + + + + +
+
+
import { Box, Typography } from '@mui/material';
+import Avatar from '@mui/material/Avatar';
+import { useEffect, useState } from 'react';
+import numFormatter from '../../../utils/MembersNum';
+import followRequest from './FollowServer';
+import {
+  TextP, Text, TextContainer, OneSuggeest, Joined,
+} from './style';
+/**
+ * Search by people
+ * @component
+ * @property  {function} handleJoin send follow to backend
+ * @property  {function} handleMouseIn when hover set buttom value to unfollow
+ * @property  {function} handleMouseOut when out of hover set button value to follow
+
+ * @return {React.Component} - Search by people
+ */
+function Peoples(props) {
+  const { people } = props;
+  const [follow, setFollow] = useState(true);
+  const handleJoin = async () => {
+    await setFollow((prev) => !prev);
+    followRequest(people?.userName, !follow);
+  };
+
+  const [hover, setHover] = useState(false);
+
+  const handleMouseIn = () => {
+    setHover(true);
+  };
+  const handleMouseOut = () => {
+    setHover(false);
+  };
+  useEffect(() => {
+    setFollow(people?.isFollowed);
+  }, []);
+  return (
+    <OneSuggeest sx={{ display: 'flex', justifyContent: 'space-between' }}>
+      <Box sx={{ display: 'flex' }}>
+
+        <Avatar alt="Remy Sharp" src={people?.profilePicture} />
+        <Box sx={{ display: 'flex', flexDirection: 'column' }}>
+          <TextContainer>
+            <Text to={`/user/${people?.userName}`}>
+              U/
+              {people?.userName}
+            </Text>
+            <Typography component="span" mx="4px" sx={{ fontSize: '6px', display: 'flex', alignItems: 'center' }}>
+              โ€ข
+            </Typography>
+            <TextP>
+              {numFormatter((people.postKarma * 1) + (people.commentKarma * 1))}
+              {' '}
+              karma
+            </TextP>
+          </TextContainer>
+          <Typography component="span" mx="4px" sx={{ fontSize: '12px', display: 'flex', alignItems: 'center' }}>
+            {people?.description}
+          </Typography>
+
+        </Box>
+      </Box>
+      <Joined
+        variant="outlined"
+        onClick={handleJoin}
+        onMouseEnter={handleMouseIn}
+        onMouseLeave={handleMouseOut}
+      >
+        {(follow) ? ((hover) ? 'Unfollow' : 'Following') : 'follow'}
+      </Joined>
+    </OneSuggeest>
+  );
+}
+export default Peoples;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_PersonalReddit_PersonalReddit.jsx.html b/docs/components_Search_PersonalReddit_PersonalReddit.jsx.html new file mode 100644 index 00000000..39a3ab35 --- /dev/null +++ b/docs/components_Search_PersonalReddit_PersonalReddit.jsx.html @@ -0,0 +1,81 @@ + + + + + JSDoc: Source: components/Search/PersonalReddit/PersonalReddit.jsx + + + + + + + + + + +
+ +

Source: components/Search/PersonalReddit/PersonalReddit.jsx

+ + + + + + +
+
+
import FormDialog from '../../HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/PopUp';
+import {
+  RedditPersonal, Paragraph, RedditImage, MiddleBox, UpperImage, CustomLink,
+} from './styles';
+
+/**
+ * pesronal reddit in search by posts sidebar
+ * @component
+
+ * @return {React.Component} - pesronal reddit in search by posts sidebar
+ */
+function PersonalReddit() {
+  return (
+    <RedditPersonal>
+      <UpperImage src="https://www.redditstatic.com/desktop2x/img/search-results-community-banner.png" />
+      <MiddleBox>
+        <RedditImage src="https://www.redditstatic.com/desktop2x/img/snoo-thinking.png" />
+      </MiddleBox>
+      <Paragraph>
+        Have an idea for a new community?
+        {' '}
+      </Paragraph>
+      <CustomLink>
+        <FormDialog />
+      </CustomLink>
+    </RedditPersonal>
+  );
+}
+
+export default PersonalReddit;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_Post_Post.jsx.html b/docs/components_Search_Post_Post.jsx.html new file mode 100644 index 00000000..f95b97bb --- /dev/null +++ b/docs/components_Search_Post_Post.jsx.html @@ -0,0 +1,172 @@ + + + + + JSDoc: Source: components/Search/Post/Post.jsx + + + + + + + + + + +
+ +

Source: components/Search/Post/Post.jsx

+ + + + + + +
+
+
import {
+  Avatar, Box, Typography,
+} from '@mui/material';
+import { useState } from 'react';
+import numFormatter from '../../../utils/MembersNum';
+import calculateTime from '../../../utils/calculateTime';
+import {
+  PostContainer, PostInfo, PostInfoLink, PostTitle,
+  PostRich, PostMedia, Image, Video, Flair, PostUrl, PostUrlLink, LinkIcon,
+  // Flair,
+} from './styles';
+
+/**
+ * Posts in search by posts
+ * @component
+
+ * @return {React.Component} - Posts in search by posts
+ */
+
+function Post(props) {
+  const { post } = props;
+  const [type] = useState('');
+
+  return (
+    <PostContainer my={2} sx={{ '&:hover': { border: 1 }, padding: '8px 16px 4px' }}>
+      <Box width="100%">
+        <PostInfo py={1}>
+          <Avatar
+            src={post?.owner?.icon}
+            sx={{
+              width: 20,
+              height: 20,
+            }}
+            alt="Profile Image"
+          />
+          <PostInfoLink to={`/r/${post?.owner?.fixedName}`} color="#000" fontWeight="bolder">
+            r/
+            {post.owner.name}
+          </PostInfoLink>
+          <Box color="#787C7E" fontWeight={300} display="flex" gap="4px" flexWrap="wrap">
+            <span>
+              โ€ข
+            </span>
+            <div>Posted By</div>
+            <Avatar
+              src={post?.author?.profilePicture}
+              sx={{
+                width: 20,
+                height: 20,
+              }}
+              alt="Profile Image"
+            />
+            <PostInfoLink to={`/user/${post?.author?.userName}`} color="inherit" fontWeight="normal">
+              u/
+              {post?.author?.displayName}
+              {' '}
+              {calculateTime(post?.createdAt)}
+            </PostInfoLink>
+          </Box>
+        </PostInfo>
+
+        <PostTitle to={`../subreddit/${post?.owner?.fixedName}/comments/${post?._id}`}>
+          <Typography variant="div" component="div" sx={{ fontSize: 18, wordBreak: 'break-all' }}>
+            {post.title.replace(/<[^>]+>/g, '')}
+            {/* {post?.title} */}
+
+            {
+            post?.flairId
+            && (
+            <Flair
+              disableRipple
+              backgroundColor={post?.flairId?.backgroundColor}
+              flairColor={post?.flairId?.textColor}
+            >
+              {/* {post.flairId.text.replace(/<[^>]+>/g, '')} */}
+              {post?.flairId?.text}
+            </Flair>
+            )
+          }
+          </Typography>
+          {(post.kind === 'video' || type === 'image')
+          && (
+          <PostMedia>
+            {(post.kind === 'video')
+            && <Video src={post?.video} alt="" />}
+            {(type === 'image')
+             && <Image src={post?.images[0]} alt="" />}
+          </PostMedia>
+          )}
+
+        </PostTitle>
+        {(post.kind === 'link')
+            && (
+            <PostUrl href={post?.url}>
+              <PostUrlLink>
+                {post?.url}
+              </PostUrlLink>
+              <LinkIcon />
+            </PostUrl>
+            )}
+        <PostRich mt={5}>
+          <Typography variant="span" sx={{ marginRight: 3 }}>
+            {numFormatter(post?.votes)}
+            {' '}
+            upvotes
+            {' '}
+          </Typography>
+          <Typography variant="span" sx={{ marginRight: 3 }}>
+            {numFormatter(post?.commentCount)}
+            {' '}
+            comments
+            {' '}
+          </Typography>
+        </PostRich>
+      </Box>
+
+    </PostContainer>
+  );
+}
+
+export default Post;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_Posts_Posts.jsx.html b/docs/components_Search_Posts_Posts.jsx.html new file mode 100644 index 00000000..356be789 --- /dev/null +++ b/docs/components_Search_Posts_Posts.jsx.html @@ -0,0 +1,80 @@ + + + + + JSDoc: Source: components/Search/Posts/Posts.jsx + + + + + + + + + + +
+ +

Source: components/Search/Posts/Posts.jsx

+ + + + + + +
+
+
import { useLocation } from 'react-router-dom';
+import { useMemo } from 'react';
+import SortType from './Sort/Sort';
+import TimeType from './Sort/Time';
+import { Header } from './Sort/style';
+/**
+ * Search type in search by posts
+ * @component
+
+ * @return {React.Component} - Search type in search by posts
+ */
+function SearchHeader() {
+  function useQuery() {
+    const { search } = useLocation();
+
+    return useMemo(() => new URLSearchParams(search), [search]);
+  }
+  const query = useQuery();
+  const Sort = query.get('sort') || 'new';
+  return (
+    <Header>
+      <SortType />
+      {(Sort === 'top' || Sort === 'comments')
+      && <TimeType />}
+    </Header>
+  );
+}
+
+export default SearchHeader;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_Posts_Sort_Sort.jsx.html b/docs/components_Search_Posts_Sort_Sort.jsx.html new file mode 100644 index 00000000..d506e0b7 --- /dev/null +++ b/docs/components_Search_Posts_Sort_Sort.jsx.html @@ -0,0 +1,161 @@ + + + + + JSDoc: Source: components/Search/Posts/Sort/Sort.jsx + + + + + + + + + + +
+ +

Source: components/Search/Posts/Sort/Sort.jsx

+ + + + + + +
+
+
import * as React from 'react';
+import MoreHorizOutlinedIcon from '@mui/icons-material/MoreHorizOutlined';
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
+import ExpandLessIcon from '@mui/icons-material/ExpandLess';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+
+import { useNavigate, useSearchParams } from 'react-router-dom';
+
+import {
+  Box,
+} from '@mui/material';
+import {
+  ShowMoreList, ShowMoreListItemText, ListItemButton, Fab,
+} from './style';
+
+/**
+ * Search by posts sort type
+ * @component
+ * @property  {function} handleClick  navigate and change sort type
+ * @property  {function} showSort show and hide the sort list
+ * @property  {function} handleClickAway close list when click out
+
+ * @return {React.Component} - Search by posts sort type
+ */
+export default function SortType() {
+  const [Openort, setOpenSort] = React.useState(false);
+
+  const [searchParams] = useSearchParams();
+  const type = searchParams.get('type') || 'posts';
+
+  const Sort = searchParams.get('sort') || 'new';
+  const navigate = useNavigate();
+  const qery = searchParams.get('q');
+  // navigate
+  const handleClick = (subPage) => {
+    navigate(`?q=${qery}&type=${type}&sort=${subPage}`);
+  };
+
+  // show and hide the sort list
+  const showSort = () => {
+    setOpenSort(!Openort);
+  };
+
+  // close list when click out
+  const handleClickAway = () => {
+    setOpenSort(false);
+  };
+  return (
+    <Box position="relative" display="flex">
+      <ClickAwayListener onClickAway={handleClickAway}>
+        <Fab
+          variant="extended"
+          size="small"
+          onClick={showSort}
+        >
+          {Sort}
+          {!Openort && (
+          <ExpandMoreIcon
+            sx={{
+              borderRadius: '10%',
+              py: 0.4,
+            }}
+          >
+            <MoreHorizOutlinedIcon />
+          </ExpandMoreIcon>
+          )}
+          {Openort && (
+          <ExpandLessIcon
+            sx={{
+              borderRadius: '10%',
+              py: 0.4,
+            }}
+            onClick={showSort}
+          >
+            {Sort}
+            <MoreHorizOutlinedIcon />
+          </ExpandLessIcon>
+          )}
+        </Fab>
+      </ClickAwayListener>
+      <ShowMoreList display={(Openort === false ? 'none' : 'block')}>
+        {/* <ListItemButton onClick={() => { setOpenSort(!Openort); handleClick('Relevance'); }}>
+          <ShowMoreListItemText Condition={(Sort.toString() === 'Relevance' || Sort === 'Sort').toString()}>
+            Relevance
+          </ShowMoreListItemText>
+        </ListItemButton> */}
+        <ListItemButton onClick={() => { setOpenSort(!Openort); handleClick('hot'); }}>
+          <ShowMoreListItemText Condition={(Sort.toString() === 'hot' || Sort === 'Sort').toString()}>
+            Hot
+          </ShowMoreListItemText>
+        </ListItemButton>
+        <ListItemButton onClick={() => { setOpenSort(!Openort); handleClick('top'); }}>
+          <ShowMoreListItemText Condition={(Sort.toString() === 'top').toString()}>
+            Top
+          </ShowMoreListItemText>
+        </ListItemButton>
+        <ListItemButton onClick={() => { setOpenSort(!Openort); handleClick('new'); }}>
+          <ShowMoreListItemText Condition={(Sort.toString() === 'new').toString()}>
+            New
+          </ShowMoreListItemText>
+        </ListItemButton>
+        <ListItemButton onClick={() => { setOpenSort(!Openort); handleClick('comments'); }}>
+          <ShowMoreListItemText Condition={(Sort.toString() === 'comments').toString()}>
+            Most Comments
+          </ShowMoreListItemText>
+        </ListItemButton>
+      </ShowMoreList>
+    </Box>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_Posts_Sort_Time.jsx.html b/docs/components_Search_Posts_Sort_Time.jsx.html new file mode 100644 index 00000000..aaf7a8c6 --- /dev/null +++ b/docs/components_Search_Posts_Sort_Time.jsx.html @@ -0,0 +1,165 @@ + + + + + JSDoc: Source: components/Search/Posts/Sort/Time.jsx + + + + + + + + + + +
+ +

Source: components/Search/Posts/Sort/Time.jsx

+ + + + + + +
+
+
import * as React from 'react';
+import MoreHorizOutlinedIcon from '@mui/icons-material/MoreHorizOutlined';
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
+import ExpandLessIcon from '@mui/icons-material/ExpandLess';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+import {
+  Box,
+} from '@mui/material';
+import { useNavigate, useSearchParams } from 'react-router-dom';
+import {
+  ShowMoreList, ShowMoreListItemText, ListItemButton, Fab,
+} from './style';
+
+/**
+ * Search by posts time type
+ * @component
+ * @property  {function} handleClick  navigate and change sort type
+ * @property  {function} showTime show and hide the time list
+ * @property  {function} handleClickAway close list when click out
+
+ * @return {React.Component} - Search by posts time type
+ */
+
+export default function TimeType() {
+  const [Time, setTime] = React.useState(false);
+
+  const [searchParams] = useSearchParams();
+  const sort = searchParams.get('sort') || 'new';
+  const type = searchParams.get('type') || 'posts';
+
+  const t = searchParams.get('t') || 'day';
+  const navigate = useNavigate();
+  const qery = searchParams.get('q');
+
+  // navigate
+  const handleClick = (subPage) => {
+    navigate(`?q=${qery}&type=${type}&sort=${sort}&t=${subPage}`);
+  };
+
+  // show and hide the time list
+  const showTime = () => {
+    setTime(!Time);
+  };
+  // close list when click out
+  const handleClickAway = () => {
+    setTime(false);
+  };
+  return (
+    <Box position="relative" display="flex">
+      <ClickAwayListener onClickAway={handleClickAway}>
+        <Fab
+          variant="extended"
+          size="small"
+          onClick={showTime}
+        >
+          {t}
+          {!Time && (
+          <ExpandMoreIcon
+            sx={{
+              borderRadius: '10%',
+            }}
+          >
+            <MoreHorizOutlinedIcon />
+          </ExpandMoreIcon>
+          )}
+          {Time && (
+          <ExpandLessIcon
+            sx={{
+              borderRadius: '10%',
+            }}
+            onClick={showTime}
+          >
+            {t}
+            <MoreHorizOutlinedIcon />
+          </ExpandLessIcon>
+          )}
+        </Fab>
+      </ClickAwayListener>
+
+      <ShowMoreList display={(Time === false ? 'none' : 'block')}>
+        <ListItemButton onClick={() => { setTime(!Time); handleClick('all'); }}>
+          <ShowMoreListItemText Condition={(t === 'all').toString()}>
+            All Time
+          </ShowMoreListItemText>
+        </ListItemButton>
+        <ListItemButton onClick={() => { setTime(!Time); handleClick('year'); }}>
+          <ShowMoreListItemText Condition={(t === 'year').toString()}>
+            Past Year
+          </ShowMoreListItemText>
+        </ListItemButton>
+        <ListItemButton onClick={() => { setTime(!Time); handleClick('month'); }}>
+          <ShowMoreListItemText Condition={(t === 'month').toString()}>
+            Past Month
+          </ShowMoreListItemText>
+        </ListItemButton>
+        <ListItemButton onClick={() => { setTime(!Time); handleClick('week'); }}>
+          <ShowMoreListItemText Condition={(t === 'week').toString()}>
+            Past Week
+          </ShowMoreListItemText>
+        </ListItemButton>
+        <ListItemButton onClick={() => { setTime(!Time); handleClick('day'); }}>
+          <ShowMoreListItemText Condition={(t === 'day' || t === 'Time').toString()}>
+            Past 24 Hours
+          </ShowMoreListItemText>
+        </ListItemButton>
+        <ListItemButton onClick={() => { setTime(!Time); handleClick('hour'); }}>
+          <ShowMoreListItemText Condition={(t === 'hour').toString()}>
+            Past Hour
+          </ShowMoreListItemText>
+        </ListItemButton>
+      </ShowMoreList>
+    </Box>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_SearchByComments_SearchByComments.jsx.html b/docs/components_Search_SearchByComments_SearchByComments.jsx.html new file mode 100644 index 00000000..cc6eb63a --- /dev/null +++ b/docs/components_Search_SearchByComments_SearchByComments.jsx.html @@ -0,0 +1,125 @@ + + + + + JSDoc: Source: components/Search/SearchByComments/SearchByComments.jsx + + + + + + + + + + +
+ +

Source: components/Search/SearchByComments/SearchByComments.jsx

+ + + + + + +
+
+
// import { useEffect, useState } from 'react';
+// import InfiniteScroll from 'react-infinite-scroll-component';
+// import { useSearchParams } from 'react-router-dom';
+import { Box, Typography } from '@mui/material';
+// import cleanPage from '../../../utils/cleanPage';
+// import { useListingContext } from '../../../contexts/ListingContext';
+import Comments from '../Comments/Comments';
+
+// import GetSearchData from '../Server';
+// import GetSearchData from '../Server2';
+
+import {
+  NotFoundBox, NotFountImage,
+  // SearchByCommunitiesHeader
+} from './style';
+
+/**
+ *  Search by comments container
+ * @component
+
+ * @return {React.Component} -  Search by comments container
+ */
+function SearchByComments(props) {
+  const { communities } = props;
+  // const [searchParams] = useSearchParams();
+  // const sort = searchParams.get('sort') || 'new';
+  // const t = searchParams.get('t') || 'day';
+  // const [comments, setComments] = useState([]);
+  // const [data] = GetSearchData('/search', q, 'comments', sort, t);
+  // const [exist, setExist] = useState(true);
+
+  // useEffect(() => {
+  //   if (data?.length === 0 || !data) {
+  //     setExist(true);
+  //   }
+  //   setComments(data);
+  // }, [data]);
+
+  // const { setPage } = useListingContext();
+
+  // const fetchMoreData = () => {
+  //   // console.log('bazwed', page);
+  //   setPage((page) => page + 1);
+  // };
+  // cleanPage();
+
+  return (
+    (communities?.length > 0)
+      ? (
+    // <SearchByCommunitiesHeader>
+    //   <InfiniteScroll
+    //     next={fetchMoreData}
+    //     hasMore
+    //     dataLength={communities?.length}
+    //   >
+        <Box>
+          {communities?.map((comm) => (
+
+            <Comments Comment={comm} />
+          ))}
+        </Box>
+    //   </InfiniteScroll>
+    // </SearchByCommunitiesHeader>
+      )
+      : (
+        <NotFoundBox>
+          <NotFountImage src="https://www.redditstatic.com/desktop2x/img/telescope-snoo.png" />
+          <Typography sx={{ fontWeight: 700, marginBottom: 2, fontSize: '18px' }}>Sorry,we cant find any data about this search</Typography>
+        </NotFoundBox>
+      )
+  );
+}
+
+export default SearchByComments;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_SearchByCommunity_SearchByCommunity.jsx.html b/docs/components_Search_SearchByCommunity_SearchByCommunity.jsx.html new file mode 100644 index 00000000..c459475f --- /dev/null +++ b/docs/components_Search_SearchByCommunity_SearchByCommunity.jsx.html @@ -0,0 +1,143 @@ + + + + + JSDoc: Source: components/Search/SearchByCommunity/SearchByCommunity.jsx + + + + + + + + + + +
+ +

Source: components/Search/SearchByCommunity/SearchByCommunity.jsx

+ + + + + + +
+
+
// import { useEffect, useMemo, useState } from 'react';
+// import InfiniteScroll from 'react-infinite-scroll-component';
+// import { useSearchParams } from 'react-router-dom';
+import { Box, Typography } from '@mui/material';
+// import { useEffect, useState } from 'react';
+
+// import cleanPage from '../../../utils/cleanPage';
+// import { useListingContext } from '../../../contexts/ListingContext';
+
+// import GetSearchData from '../Server';
+
+// import GetSearchData from '../Server2';
+
+import Subreddits from '../Subreddits/Subreddits';
+import {
+  NotFoundBox, NotFountImage,
+  // SearchByCommunitiesHeader
+} from './style';
+
+/**
+ * Search by communities container
+ * @component
+
+ * @return {React.Component} -  Search by communities container
+ */
+function SearchByCommunity(props) {
+  const { communities } = props;
+  // const [searchParams] = useSearchParams();
+  // const sort = searchParams.get('sort') || 'new';
+  // const t = searchParams.get('t') || 'day';
+  // const [communities, setCommunities] = useState([]);
+  // const [data] = GetSearchData('/search', q, 'communities', sort, t);
+  // const value2 = useMemo(() => ({ data }), [data]);
+  // console.log(value2);
+  // console.log(data);
+  // const [exist, setExist] = useState(true);
+
+  // useEffect(() => {
+  //   if (data?.length === 0 || !data) {
+  //     setExist(true);
+  //   }
+  //   setCommunities(data);
+  //   console.log(communities);
+  // }, [data]);
+
+  // useEffect(() => {
+  //   console.log(communities);
+  //   console.log(communities.length);
+  // }, [communities]);
+  // const { setPage } = useListingContext();
+
+  // const fetchMoreData = () => {
+  //   // console.log('bazwed', page);
+  //   setPage((page) => page + 1);
+  // };
+  // cleanPage();
+  // const [exist1, setExist] = useState(true);
+
+  // useEffect(() => {
+  //   if (communities?.length === 0 || communities == null) { setExist(true); }
+  // }, [communities]);
+  return (
+    (communities?.length > 0)
+      ? (
+    // <SearchByCommunitiesHeader>
+    //   {communities && (
+    //   <InfiniteScroll
+    //     next={fetchMoreData}
+    //     hasMore
+    //     dataLength={communities?.length}
+    //   >
+        <Box>
+          {communities?.map((subreddit) => (
+
+            <Subreddits subreddit={subreddit} />
+          ))}
+        </Box>
+    //   </InfiniteScroll>
+    //   )}
+
+    // </SearchByCommunitiesHeader>
+      )
+      : (
+        <NotFoundBox>
+          <NotFountImage src="https://www.redditstatic.com/desktop2x/img/telescope-snoo.png" />
+          <Typography sx={{ fontWeight: 700, marginBottom: 2, fontSize: '18px' }}>Sorry,we cant find any data about this search</Typography>
+        </NotFoundBox>
+      )
+  );
+}
+
+export default SearchByCommunity;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_SearchByPeople_SearchByPeople.jsx.html b/docs/components_Search_SearchByPeople_SearchByPeople.jsx.html new file mode 100644 index 00000000..bf60daf1 --- /dev/null +++ b/docs/components_Search_SearchByPeople_SearchByPeople.jsx.html @@ -0,0 +1,124 @@ + + + + + JSDoc: Source: components/Search/SearchByPeople/SearchByPeople.jsx + + + + + + + + + + +
+ +

Source: components/Search/SearchByPeople/SearchByPeople.jsx

+ + + + + + +
+
+
// import { useEffect, useState } from 'react';
+// import InfiniteScroll from 'react-infinite-scroll-component';
+// import { useSearchParams } from 'react-router-dom';
+// import { Typography } from '@mui/material';
+// import cleanPage from '../../../utils/cleanPage';
+// import { useListingContext } from '../../../contexts/ListingContext';
+import { Box, Typography } from '@mui/material';
+import Peoples from '../Peoples/People';
+
+// import GetSearchData from '../Server';
+// import GetSearchData from '../Server2';
+
+import {
+  NotFoundBox, NotFountImage,
+  // SearchByCommunitiesHeader
+} from './style';
+
+/**
+ *  Search by people container
+ * @component
+
+ * @return {React.Component} -  Search by people container
+ */
+function SearchByPeople(props) {
+  const { people } = props;
+  // const [searchParams] = useSearchParams();
+  // const sort = searchParams.get('sort') || 'new';
+  // const t = searchParams.get('t') || 'day';
+  // const [people, setPeople] = useState([]);
+  // const [data] = GetSearchData('/search', q, 'people', sort, t);
+  // const [exist, setExist] = useState(true);
+
+  // const { setPage } = useListingContext();
+
+  // const fetchMoreData = () => {
+  //   // console.log('bazwed', page);
+  //   setPage((page) => page + 1);
+  // };
+  // cleanPage();
+  // useEffect(() => {
+  //   if (data?.length === 0 || !data) {
+  //     setExist(true);
+  //   }
+  //   setPeople(data);
+  // }, [data]);
+  return (
+    (people?.length > 0)
+      ? (
+    // <SearchByCommunitiesHeader>
+    //   <InfiniteScroll
+    //     next={fetchMoreData}
+    //     hasMore
+    //     dataLength={people?.length}
+    //   >
+        <Box>
+          {people?.map((peoplee) => (
+
+            <Peoples people={peoplee} />
+          ))}
+        </Box>
+    //   </InfiniteScroll>
+    // </SearchByCommunitiesHeader>
+      )
+      : (
+        <NotFoundBox>
+          <NotFountImage src="https://www.redditstatic.com/desktop2x/img/telescope-snoo.png" />
+          <Typography sx={{ fontWeight: 700, marginBottom: 2, fontSize: '18px' }}>Sorry,we cant find any data about this search</Typography>
+        </NotFoundBox>
+      )
+  );
+}
+
+export default SearchByPeople;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_SearchByPosts_SearchByPosts.jsx.html b/docs/components_Search_SearchByPosts_SearchByPosts.jsx.html new file mode 100644 index 00000000..bbe22e1e --- /dev/null +++ b/docs/components_Search_SearchByPosts_SearchByPosts.jsx.html @@ -0,0 +1,150 @@ + + + + + JSDoc: Source: components/Search/SearchByPosts/SearchByPosts.jsx + + + + + + + + + + +
+ +

Source: components/Search/SearchByPosts/SearchByPosts.jsx

+ + + + + + +
+
+
// import { useEffect, useState } from 'react';
+// import InfiniteScroll from 'react-infinite-scroll-component';
+// import { useSearchParams } from 'react-router-dom';
+import { Box, Typography } from '@mui/material';
+// import { useListingContext } from '../../../contexts/ListingContext';
+
+// import GetSearchData from '../Server';
+// import GetSearchData from '../Server2';
+
+// import { useEffect, useState } from 'react';
+import {
+  NotFoundBox, NotFountImage,
+  // PostsContainer, PostsContainer2,
+} from './style';
+import PostsCom from '../Post/Post';
+// import SideBar from '../SideBar/SideBar';
+// import cleanPage from '../../../utils/cleanPage';
+
+/**
+ *  Search by posts container
+ * @component
+
+ * @return {React.Component} - Search by posts container
+ */
+function SearchByPosts(props) {
+  const { posts } = props;
+
+  // const [searchParams] = useSearchParams();
+  // const sort = searchParams.get('sort') || 'new';
+  // const t = searchParams.get('t') || 'day';
+  // const [posts, setPosts] = useState([]);
+  // const [communities, setCommunities] = useState([]);
+  // const [people, setPeople] = useState([]);
+  // const [data] = GetSearchData('/search', q, 'posts', sort, t);
+
+  // const [data2] = GetSearchData('/search', q, 'communities', sort, t);
+
+  // const [data3] = GetSearchData('/search', q, 'people', sort, t);
+
+  // useEffect(() => {
+  //   setPosts(data);
+  //   console.log(data);
+  //   // if (!data2 || data2?.length === 0) {
+  //   setCommunities(data2?.slice(0, 3));
+  //   // }
+  //   // if (!data3 || data3?.length === 0) {
+  //   setPeople(data3?.slice(0, 3));
+  //   // }
+  //   // if (data?.length === 0 || !data) {
+  //   //   console.log(data?.length === 0 || !data);
+  //   //   setExist(true);
+  //   // }
+  //   setExist(true);
+  //   console.log('barrraaaaaaaaaaaaa', data?.length === 0 || !data);
+  // }, [data, data2, data3]);
+
+  // const { setPage } = useListingContext();
+
+  // const fetchMoreData = () => {
+  //   // console.log('bazwed', page);
+  //   setPage((page) => page + 1);
+  // };
+  // cleanPage();
+  // const [exist1, setExist] = useState(true);
+
+  // useEffect(() => {
+  //   if (posts?.length === 0) { setExist(true); }
+  // }, [posts]);
+  return (
+    (posts?.length > 0)
+      ? (
+    // <PostsContainer2>
+    //   <PostsContainer>
+    //     <InfiniteScroll
+    //       next={fetchMoreData}
+    //       hasMore
+    //       dataLength={posts?.length}
+    //     >
+        <Box>
+          {posts?.map((p) => (
+
+            <PostsCom post={p} />
+          ))}
+        </Box>
+    //   </InfiniteScroll>
+    // </PostsContainer>
+    //   <SideBar peoples={people} subreddits={communities} />
+    // </PostsContainer2>
+      )
+      : (
+        <NotFoundBox>
+          <NotFountImage src="https://www.redditstatic.com/desktop2x/img/telescope-snoo.png" />
+          <Typography sx={{ fontWeight: 700, marginBottom: 2, fontSize: '18px' }}>Sorry,we cant find any data about this search</Typography>
+        </NotFoundBox>
+      )
+  );
+}
+
+export default SearchByPosts;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_SideBar_Community_Community.jsx.html b/docs/components_Search_SideBar_Community_Community.jsx.html new file mode 100644 index 00000000..a4f43221 --- /dev/null +++ b/docs/components_Search_SideBar_Community_Community.jsx.html @@ -0,0 +1,86 @@ + + + + + JSDoc: Source: components/Search/SideBar/Community/Community.jsx + + + + + + + + + + +
+ +

Source: components/Search/SideBar/Community/Community.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import Suggestions from './Suggestions';
+import {
+  CommunityString, Suggestion, ShowMore,
+} from './style';
+
+/**
+ * Search by posts sidebar community section
+ * @component
+
+ * @return {React.Component} - Search by posts sidebar community section
+ */
+
+function Community(props) {
+  const { subreddits } = props;
+  return (
+    <Box>
+      <CommunityString>Communities</CommunityString>
+      <Suggestion>
+        {/* <Suggestions />
+        <Suggestions />
+        <Suggestions /> */}
+        {subreddits?.map((subreddit) => (
+
+          <Suggestions subreddit={subreddit} />
+        ))}
+
+      </Suggestion>
+      <Box sx={{ display: 'flex', justifyContent: 'flex-start' }}>
+        <ShowMore>See More Communities</ShowMore>
+      </Box>
+    </Box>
+  );
+}
+export default Community;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_SideBar_Community_Suggestions.jsx.html b/docs/components_Search_SideBar_Community_Suggestions.jsx.html new file mode 100644 index 00000000..6cb2f785 --- /dev/null +++ b/docs/components_Search_SideBar_Community_Suggestions.jsx.html @@ -0,0 +1,117 @@ + + + + + JSDoc: Source: components/Search/SideBar/Community/Suggestions.jsx + + + + + + + + + + +
+ +

Source: components/Search/SideBar/Community/Suggestions.jsx

+ + + + + + +
+
+
import Avatar from '@mui/material/Avatar';
+import { useState } from 'react';
+import PostJoin from '../../../SubReddit/PostJoin';
+import numFormatter from '../../../../utils/MembersNum';
+import {
+  TextP, Text, TextContainer, OneSuggeest, Joined,
+} from './style';
+/**
+ * Search by community entity in sidebar
+ * @component
+ * @property  {function} handleJoin send join to backend
+ * @property  {function} handleMouseIn when hover set buttom value to leave
+ * @property  {function} handleMouseOut when out of hover set button value to joined
+
+ * @return {React.Component} - Search by community entity in sidebar
+ */
+function Suggestions(props) {
+  const { subreddit } = props;
+  const [joined, setJoined] = useState(true);
+  const handleJoin = () => {
+    PostJoin(`/subreddits/${subreddit?.fixedName}/subscribe`, !joined);
+
+    setJoined((prev) => !prev);
+  };
+
+  const [hover, setHover] = useState(false);
+
+  const handleMouseIn = () => {
+    setHover(true);
+  };
+  const handleMouseOut = () => {
+    setHover(false);
+  }; return (
+    {
+      icon: 'https://styles.redditmedia.com/t5_3ptyd/styles/communityIcon_p18jqwszxcv51.png',
+      _id: 10,
+      fixedName: 'uniquesubreddit',
+      membersCount: 10000,
+      description: 'welcome to subreddit',
+    },
+
+      <OneSuggeest>
+        <Avatar alt="Remy Sharp" src={subreddit?.icon} />
+        <TextContainer>
+          <Text to="/r/$subreddit?.fixedName}">
+            r/
+            {subreddit?.fixedName}
+          </Text>
+          <TextP>
+            { numFormatter(subreddit?.membersCount)}
+            {' '}
+            Members
+          </TextP>
+        </TextContainer>
+        <Joined
+          variant="outlined"
+          onClick={handleJoin}
+          onMouseEnter={handleMouseIn}
+          onMouseLeave={handleMouseOut}
+        >
+          {(joined ? (hover ? 'leave' : 'joined') : 'join')}
+        </Joined>
+      </OneSuggeest>
+  );
+}
+export default Suggestions;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_SideBar_People_People.jsx.html b/docs/components_Search_SideBar_People_People.jsx.html new file mode 100644 index 00000000..38592635 --- /dev/null +++ b/docs/components_Search_SideBar_People_People.jsx.html @@ -0,0 +1,81 @@ + + + + + JSDoc: Source: components/Search/SideBar/People/People.jsx + + + + + + + + + + +
+ +

Source: components/Search/SideBar/People/People.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import Suggestions from './Suggestions';
+import {
+  PeopleString, ShowMore, Suggestion,
+} from './style';
+/**
+ * Search by posts sidebar people section
+ * @component
+
+ * @return {React.Component} - Search by posts sidebar people section
+ */
+function People(props) {
+  const { peoples } = props;
+  return (
+    <Box sx={{ width: 310 }}>
+      <PeopleString>People</PeopleString>
+      <Suggestion>
+        {peoples?.map((people) => (
+
+          <Suggestions people={people} />
+        ))}
+      </Suggestion>
+      <Box sx={{ display: 'flex', justifyContent: 'cenetr' }}>
+        <ShowMore>See More Communities</ShowMore>
+      </Box>
+
+    </Box>
+  );
+}
+export default People;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_SideBar_People_Suggestions.jsx.html b/docs/components_Search_SideBar_People_Suggestions.jsx.html new file mode 100644 index 00000000..34d069b7 --- /dev/null +++ b/docs/components_Search_SideBar_People_Suggestions.jsx.html @@ -0,0 +1,108 @@ + + + + + JSDoc: Source: components/Search/SideBar/People/Suggestions.jsx + + + + + + + + + + +
+ +

Source: components/Search/SideBar/People/Suggestions.jsx

+ + + + + + +
+
+
import Avatar from '@mui/material/Avatar';
+import { useState } from 'react';
+import followRequest from '../../Peoples/FollowServer';
+import numFormatter from '../../../../utils/MembersNum';
+import {
+  TextP, Text, TextContainer, OneSuggeest, Joined,
+} from './style';
+/**
+ * people in sidebar entity
+ * @component
+ * @property  {function} handleJoin send follow to backend
+ * @property  {function} handleMouseIn when hover set buttom value to unfollow
+ * @property  {function} handleMouseOut when out of hover set button value to follow
+
+ * @return {React.Component} - people in sidebar entity
+ */
+function Suggestions(props) {
+  const { people } = props;
+  const [follow, setFollow] = useState(people?.isFollowed);
+  const handleJoin = () => {
+    followRequest(people?.userName, follow);
+    setFollow((prev) => !prev);
+  };
+  const [hover, setHover] = useState(false);
+
+  const handleMouseIn = () => {
+    setHover(true);
+  };
+  const handleMouseOut = () => {
+    setHover(false);
+  };
+  return (
+    <OneSuggeest>
+      <Avatar alt="Remy Sharp" src={people?.profilePicture} />
+      <TextContainer>
+        <Text to={`/user/${people?.userName}`}>
+          U/
+          {people?.displayName}
+        </Text>
+        <TextP>
+          {numFormatter(people.postKarma + people.commentKarma)}
+          {' '}
+          karma
+        </TextP>
+      </TextContainer>
+      <Joined
+        variant="outlined"
+        onClick={handleJoin}
+        onMouseEnter={handleMouseIn}
+        onMouseLeave={handleMouseOut}
+      >
+        {(follow ? (hover ? 'Unfollow' : 'Following') : 'follow')}
+      </Joined>
+    </OneSuggeest>
+  );
+}
+export default Suggestions;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_SideBar_SideBar.jsx.html b/docs/components_Search_SideBar_SideBar.jsx.html new file mode 100644 index 00000000..eeb6a121 --- /dev/null +++ b/docs/components_Search_SideBar_SideBar.jsx.html @@ -0,0 +1,79 @@ + + + + + JSDoc: Source: components/Search/SideBar/SideBar.jsx + + + + + + + + + + +
+ +

Source: components/Search/SideBar/SideBar.jsx

+ + + + + + +
+
+
import { SideBarContainer, CommunityContainer } from './style';
+import Community from './Community/Community';
+import People from './People/People';
+import PersonalReddit from '../PersonalReddit/PersonalReddit';
+import BackHome from '../../BackHomeBottun/BackHome';
+/**
+ * Search by posts sidebar
+ * @component
+
+ * @return {React.Component} -Search by posts sidebar
+ */
+function SideBar(props) {
+  const { subreddits, peoples } = props;
+  return (
+    <SideBarContainer>
+      <CommunityContainer>
+        <Community subreddits={subreddits} />
+      </CommunityContainer>
+      <CommunityContainer>
+        <People peoples={peoples} />
+      </CommunityContainer>
+      <PersonalReddit />
+      <BackHome />
+    </SideBarContainer>
+  );
+}
+
+export default SideBar;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Search_Subreddits_Subreddits.jsx.html b/docs/components_Search_Subreddits_Subreddits.jsx.html new file mode 100644 index 00000000..95dd954a --- /dev/null +++ b/docs/components_Search_Subreddits_Subreddits.jsx.html @@ -0,0 +1,146 @@ + + + + + JSDoc: Source: components/Search/Subreddits/Subreddits.jsx + + + + + + + + + + +
+ +

Source: components/Search/Subreddits/Subreddits.jsx

+ + + + + + +
+
+
import {
+  Avatar, Box, Typography,
+} from '@mui/material';
+import { useEffect, useState } from 'react';
+import numFormatter from '../../../utils/MembersNum';
+import PostJoin from '../../SubReddit/PostJoin';
+import {
+  Joined,
+  PostContainer, PostInfo, PostInfoLink,
+} from './style';
+
+/**
+ * Search by community
+ * @component
+ * @property  {function} handleJoin send join to backend
+ * @property  {function} handleMouseIn when hover set buttom value to leave
+ * @property  {function} handleMouseOut when out of hover set button value to joined
+
+ * @return {React.Component} - Search by community
+ */
+
+function Subreddits(props) {
+  const { subreddit } = props;
+  const [joined, setJoined] = useState(true);
+  const [action, setaction] = useState('');
+  console.log(action);
+  const handleJoin = () => {
+    if (!joined) {
+      setaction('unsub');
+    } else {
+      setaction('sub');
+    }
+    PostJoin(`/subreddits/${subreddit?.fixedName}/subscribe`, action);
+
+    setJoined((prev) => !prev);
+  };
+
+  const [hover, setHover] = useState(false);
+
+  const handleMouseIn = () => {
+    setHover(true);
+  };
+  const handleMouseOut = () => {
+    setHover(false);
+  };
+  useEffect(() => {
+    setJoined(subreddit?.isJoined);
+  }, []);
+  return (
+    <PostContainer my={2} sx={{ padding: '16px' }}>
+      <Box width="100%" sx={{ display: 'flex', justifyContent: 'space-between' }}>
+        <PostInfo sx={{ display: 'flex', flexDirection: 'raw' }}>
+          <Avatar
+            src={subreddit?.icon}
+            sx={{
+              width: 36,
+              height: 36,
+            }}
+            alt="Profile Image"
+          />
+          <Box sx={{ padding: '0 8px' }}>
+            <Box sx={{ display: 'flex' }}>
+              <PostInfoLink to={`/r/${subreddit?.fixedName}`} color="#000" fontWeight="bolder">
+                r/
+                {subreddit?.name}
+              </PostInfoLink>
+              <Box color="#787C7E" fontWeight={300} display="flex" gap="4px" flexWrap="wrap">
+                <Typography component="span" mx="4px" sx={{ fontSize: '6px', display: 'flex', alignItems: 'center' }}>
+                  โ€ข
+                </Typography>
+                <div>
+                  {numFormatter(subreddit?.membersCount)}
+                  {' '}
+                  member
+                </div>
+              </Box>
+            </Box>
+            <div>
+              {subreddit?.description}
+            </div>
+          </Box>
+        </PostInfo>
+        <Joined
+          variant="outlined"
+          onClick={handleJoin}
+          onMouseEnter={handleMouseIn}
+          onMouseLeave={handleMouseOut}
+        >
+          {((joined) ? (hover ? 'leave' : 'joined') : 'join')}
+        </Joined>
+      </Box>
+    </PostContainer>
+  );
+}
+export default Subreddits;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Settings_SettingsAccount_AccountPreferences_AccountPreferences.jsx.html b/docs/components_Settings_SettingsAccount_AccountPreferences_AccountPreferences.jsx.html new file mode 100644 index 00000000..9c1ef7c6 --- /dev/null +++ b/docs/components_Settings_SettingsAccount_AccountPreferences_AccountPreferences.jsx.html @@ -0,0 +1,142 @@ + + + + + JSDoc: Source: components/Settings/SettingsAccount/AccountPreferences/AccountPreferences.jsx + + + + + + + + + + +
+ +

Source: components/Settings/SettingsAccount/AccountPreferences/AccountPreferences.jsx

+ + + + + + +
+
+
import { useEffect, useState } from 'react';
+import { useCookies } from 'react-cookie';
+import {
+  Button, ContentHeader, Content, ContentSubHeader,
+  SubHeader, AntSwitch,
+} from '../../styles';
+import ChangeCountry from './ChangeCountry/ChangeCountry';
+import ChangeGender from './ChangeGender/ChangeGender';
+import { ChangeButton, BootstrapDialog } from './styles';
+import { redditCookie } from '../../../Authentication/authenticationServer';
+import CahngePassword from './ChangePassword/CahngePassword';
+import CahngeEmail from './ChangeEmail/ChangeEmail';
+/**
+ * - AccountPreferences
+ * - Change Email and password in settings page
+ *  @component
+ *
+ */
+function AccountPreferences() {
+  const [cookies, setCookies] = useCookies(['redditUser']);
+  const [openPass, setOpenPass] = useState(false);
+  const [openEmail, setOpenEmail] = useState(false);
+  useEffect(() => {
+    redditCookie(setCookies);
+  }, []);
+
+  return (
+    <>
+      <SubHeader data-testid="account-preferances">ACCOUNT PREFERENCES</SubHeader>
+      <Button>
+        <Content>
+          <ContentHeader>
+            Email address
+          </ContentHeader>
+          <ContentSubHeader>
+            {cookies.redditUser?.email}
+          </ContentSubHeader>
+        </Content>
+        <AntSwitch>
+          <ChangeButton onClick={() => { setOpenEmail(true); }}>Change</ChangeButton>
+        </AntSwitch>
+      </Button>
+      <Button>
+        <Content>
+          <ContentHeader>
+            Change password
+          </ContentHeader>
+          <ContentSubHeader>
+            Password must be at least 8 characters long
+          </ContentSubHeader>
+        </Content>
+        <AntSwitch>
+          <ChangeButton onClick={() => { setOpenPass(true); }}>Change</ChangeButton>
+        </AntSwitch>
+      </Button>
+      <BootstrapDialog
+        onClose={(event, reason) => {
+          if (reason !== 'backdropClick' && reason !== 'escapeKeyDown') {
+            setOpenPass(false);
+          }
+        }}
+        aria-labelledby="customized-dialog-title"
+        open={openEmail}
+        keepMounted
+      >
+        <CahngeEmail
+          setOpenEmail={setOpenEmail}
+        />
+      </BootstrapDialog>
+      <BootstrapDialog
+        onClose={(event, reason) => {
+          if (reason !== 'backdropClick' && reason !== 'escapeKeyDown') {
+            setOpenPass(false);
+          }
+        }}
+        aria-labelledby="customized-dialog-title"
+        open={openPass}
+        keepMounted
+      >
+        <CahngePassword
+          setOpenPass={setOpenPass}
+        />
+      </BootstrapDialog>
+      <ChangeGender />
+      <ChangeCountry />
+
+    </>
+  );
+}
+
+export default AccountPreferences;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Settings_SettingsAccount_AccountPreferences_ChangeCountry_ChangeCountry.jsx.html b/docs/components_Settings_SettingsAccount_AccountPreferences_ChangeCountry_ChangeCountry.jsx.html new file mode 100644 index 00000000..9500746c --- /dev/null +++ b/docs/components_Settings_SettingsAccount_AccountPreferences_ChangeCountry_ChangeCountry.jsx.html @@ -0,0 +1,143 @@ + + + + + JSDoc: Source: components/Settings/SettingsAccount/AccountPreferences/ChangeCountry/ChangeCountry.jsx + + + + + + + + + + +
+ +

Source: components/Settings/SettingsAccount/AccountPreferences/ChangeCountry/ChangeCountry.jsx

+ + + + + + +
+
+
import {
+  Box, Divider,
+} from '@mui/material';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+import { useAlert } from 'react-alert';
+import countryList from 'react-select-country-list';
+import { useState, useMemo, useContext } from 'react';
+import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
+import {
+  Button, ContentHeader, Content, ContentSubHeader, AntSwitch,
+} from '../../../styles';
+import {
+  ShowMoreList, ShowMoreListItemText, ListItemButton, Fab,
+} from './styles';
+import { SettingsContext } from '../../../../../contexts/SettingsProvider';
+import { settingsPost } from '../../../settingsServer';
+/**
+ * - ChangeCountry
+ * - Change Country of user in settings page
+ *  @component
+ *  @property {setPrefs} setValue set perfs it will be Coutry of user
+ *  @property {prefs} value perfs of user
+ *  @property {Boolean} open bool to open list or close
+ *  @property {function} handleChangeCoutry handel when
+ */
+
+function ChangeCountry() {
+  const {
+    prefs, setPrefs,
+  } = useContext(SettingsContext);
+  const alert = useAlert();
+
+  const [open, setOpen] = useState(false);
+  const options = useMemo(() => countryList().getData(), []);
+  const handleChangeCoutry = async (country) => {
+    setPrefs((oldPrefs) => ({ ...oldPrefs, country }));
+
+    const [text, type] = await settingsPost({ ...prefs, country });
+    if (text !== '') {
+      // setMessage(text);
+      // setStats(type);
+      //  setOpenAlert(true);
+      alert.show({ text, type });
+    }
+  };
+
+  return (
+    <Button sx={{ flexDirection: 'column' }}>
+      <Content>
+        <ContentHeader>
+          Country
+        </ContentHeader>
+        <ContentSubHeader>
+          This is your primary location
+        </ContentSubHeader>
+      </Content>
+      <AntSwitch sx={{ justifyContent: 'flex-start' }}>
+        <Box position="relative" display="flex">
+          <ClickAwayListener onClickAway={() => { setOpen(false); }}>
+            <Fab
+              sx={{ color: '#0079d3', fontWeight: 'bold', fontSize: '12px' }}
+              size="small"
+              onClick={() => { setOpen(!open); }}
+            >
+              {prefs?.country}
+              <ArrowDropDownIcon sx={{ color: 'black' }} />
+            </Fab>
+          </ClickAwayListener>
+          <ShowMoreList
+            sx={{ height: '200px' }}
+            display={(open === false ? 'none' : 'block')}
+          >
+            {
+                options.map((e, index) => (
+                  <div key={`${index + 0}`}>
+                    <ListItemButton onClick={() => { handleChangeCoutry(e.label.toLowerCase()); setOpen(!open); }}>
+                      <ShowMoreListItemText Condition={(prefs?.country.toLowerCase() === e.label.toLowerCase()).toString()}>
+                        {e.label}
+                      </ShowMoreListItemText>
+                    </ListItemButton>
+                    <Divider sx={{ margin: '5px' }} />
+                  </div>
+                ))
+                      }
+          </ShowMoreList>
+        </Box>
+      </AntSwitch>
+    </Button>
+  );
+}
+
+export default ChangeCountry;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Settings_SettingsAccount_SettingsAccount.jsx.html b/docs/components_Settings_SettingsAccount_SettingsAccount.jsx.html new file mode 100644 index 00000000..3306356d --- /dev/null +++ b/docs/components_Settings_SettingsAccount_SettingsAccount.jsx.html @@ -0,0 +1,130 @@ + + + + + JSDoc: Source: components/Settings/SettingsAccount/SettingsAccount.jsx + + + + + + + + + + +
+ +

Source: components/Settings/SettingsAccount/SettingsAccount.jsx

+ + + + + + +
+
+
/* eslint-disable react/function-component-definition */
+import { Box } from '@mui/system';
+import DeleteOutlineOutlinedIcon from '@mui/icons-material/DeleteOutlineOutlined';
+import { useEffect, useState } from 'react';
+import SettingsProvider from '../../../contexts/SettingsProvider';
+import {
+  Header, Button, ContentHeader, Content, ContentSubHeader,
+  SettingsPageConranier, SubHeader, AntSwitch,
+} from '../styles';
+import DeleteAccountWindow from './DeleteAccountButton/DeleteAccountButton';
+import AccountPreferences from './AccountPreferences/AccountPreferences';
+import { DeleteAccount, BootstrapDialog } from './styles';
+import { settingsFetch } from '../settingsServer';
+/**
+ * - SettingsAccount
+ * - Change Email and password in settings page
+ *  @component
+ *  @property {function} setPrefs set prefs of user
+ *  @property {Object} prefs prefs of user
+ *  @property {Object} data data from fetch
+ */
+const SettingsAccount = () => {
+  const [openPass, setOpenPass] = useState(false);
+  const [prefs, setPrefs] = useState();
+  const [data] = settingsFetch();
+  useEffect(() => {
+    setPrefs(data?.prefs);
+  }, [data]);
+  return (
+    <SettingsPageConranier data-testid="settings-account">
+      <Box sx={{ maxWidth: '688px', flex: '1 1 auto' }}>
+        <Header>Account settings</Header>
+
+        <SettingsProvider prefs={prefs} setPrefs={setPrefs}>
+          <AccountPreferences />
+        </SettingsProvider>
+
+        <SubHeader>  CONNECTED ACCOUNTS  </SubHeader>
+        <Button>
+          <Content>
+            <ContentHeader>
+              Connected to Google
+            </ContentHeader>
+            <ContentSubHeader>
+              Connect account to log in to Reddit with Google
+            </ContentSubHeader>
+          </Content>
+          <AntSwitch sx={{ color: '#0079D3' }}>
+            <Box sx={{ width: 'fit-content', cursor: 'pointer' }}> (disconnect)</Box>
+          </AntSwitch>
+        </Button>
+        <SubHeader> DELETE ACCOUNT  </SubHeader>
+        <DeleteAccount>
+          <DeleteOutlineOutlinedIcon />
+          <Box onClick={() => { setOpenPass(true); }} sx={{ fontSize: '12px' }}>
+            {' '}
+            <Box sx={{ width: 'fit-content', cursor: 'pointer' }}> DELETE ACCOUNT</Box>
+          </Box>
+        </DeleteAccount>
+        <BootstrapDialog
+          onClose={(event, reason) => {
+            if (reason !== 'backdropClick' && reason !== 'escapeKeyDown') {
+              setOpenPass(false);
+            }
+          }}
+          aria-labelledby="customized-dialog-title"
+          open={openPass}
+          keepMounted
+        >
+          <DeleteAccountWindow
+            setOpenPass={setOpenPass}
+          />
+        </BootstrapDialog>
+      </Box>
+    </SettingsPageConranier>
+
+  );
+};
+export default SettingsAccount;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Settings_SettingsAccount_VerifyEmail_verifyEmailServer.js.html b/docs/components_Settings_SettingsAccount_VerifyEmail_verifyEmailServer.js.html new file mode 100644 index 00000000..998d6703 --- /dev/null +++ b/docs/components_Settings_SettingsAccount_VerifyEmail_verifyEmailServer.js.html @@ -0,0 +1,84 @@ + + + + + JSDoc: Source: components/Settings/SettingsAccount/VerifyEmail/verifyEmailServer.js + + + + + + + + + + +
+ +

Source: components/Settings/SettingsAccount/VerifyEmail/verifyEmailServer.js

+ + + + + + +
+
+
// services
+// import DoneIcon from '@mui/icons-material/Done';
+import axios from '../../../../services/instance';
+import { redirectHome } from '../../../../utils/Redirect';
+
+// styles
+// import { wrongIcon } from '../styles';
+// import theme from '../../../styles/theme';
+
+// scripts
+// import { redirectLogin } from '../../../utils/Redirect';
+
+/**
+ *
+ * @param {string} token
+ * @returns bool if valid is true else false
+ */
+export const checkEmailToken = (token, setVerified) => {
+  // Check Token Endpoint
+  axios.post(`/users/verify_email/${token}`).then((response) => {
+    if (response.status === 204) {
+      // alert('Email Verified');
+      // setVerified('Verified');
+      redirectHome(100);
+    }
+  }).catch((error) => {
+    console.log(error);
+    if (error?.response?.status === 400) {
+      alert(error?.response?.data?.errorMessage);
+    }
+    setVerified('Error');
+  });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Settings_SettingsFeed_SettingsFeed.jsx.html b/docs/components_Settings_SettingsFeed_SettingsFeed.jsx.html new file mode 100644 index 00000000..d649b88c --- /dev/null +++ b/docs/components_Settings_SettingsFeed_SettingsFeed.jsx.html @@ -0,0 +1,130 @@ + + + + + JSDoc: Source: components/Settings/SettingsFeed/SettingsFeed.jsx + + + + + + + + + + +
+ +

Source: components/Settings/SettingsFeed/SettingsFeed.jsx

+ + + + + + +
+
+
import { Box } from '@mui/system';
+import { Switch } from '@mui/material';
+import { useState, useEffect } from 'react';
+import { useAlert } from 'react-alert';
+import {
+  AntSwitch, ContentSubHeader, ContentHeader, Content, Button, Header,
+  SettingsPageConranier, SubHeader,
+} from '../styles';
+import { settingsPost, settingsFetch } from '../settingsServer';
+/**
+ * - SettingsFeed
+ * - Change Adult content and  Autoplay media in settings page
+ *  @component
+ *  @property {function} setPrefs set prefs of user
+ *  @property {Object} prefs prefs of user
+ *  @property {Object} data data from fetch
+ */
+function SettingsFeed() {
+  const alert = useAlert();
+  const [prefs, setPrefs] = useState();
+  const [data] = settingsFetch();
+  useEffect(() => {
+    setPrefs(data?.prefs);
+  }, [data]);
+
+  const handleAdultContent = async () => {
+    setPrefs((oldPrefs) => ({ ...oldPrefs, adultContent: !oldPrefs.adultContent }));
+    const [text, type] = await settingsPost({ ...prefs, adultContent: !prefs?.adultContent });
+    if (text !== '') {
+      alert.show({ text, type });
+    }
+  };
+  const handleAutoplayMedia = async () => {
+    setPrefs((oldPrefs) => ({ ...oldPrefs, autoplayMedia: !oldPrefs.autoplayMedia }));
+    const [text, type] = await settingsPost({ ...prefs, autoplayMedia: !prefs?.autoplayMedia });
+    if (text !== '') {
+      alert.show({ text, type });
+    }
+  };
+  return (
+
+    <SettingsPageConranier data-testid="settings-feed">
+      <Box sx={{ maxWidth: '688px', flex: '1 1 auto' }}>
+        <Header>Feed settings</Header>
+        <SubHeader>CONTENT PREFERENCES</SubHeader>
+        <Button>
+          <Content>
+            <ContentHeader>
+              Adult content
+            </ContentHeader>
+            <ContentSubHeader>
+              Enable to view adult and NSFW (not safe for work) content in your feed and search results.
+            </ContentSubHeader>
+          </Content>
+          <AntSwitch onClick={() => { handleAdultContent(); }}>
+            <Switch checked={prefs?.adultContent || false} />
+          </AntSwitch>
+        </Button>
+        <Button>
+          <Content>
+            <ContentHeader>
+              Autoplay media
+            </ContentHeader>
+            <ContentSubHeader>
+              Play videos and gifs automatically when in the viewport.
+            </ContentSubHeader>
+          </Content>
+          <AntSwitch onClick={() => { handleAutoplayMedia(); }}>
+            <Switch checked={prefs?.autoplayMedia || false} inputProps={{ 'aria-label': 'controlled' }} />
+
+          </AntSwitch>
+        </Button>
+      </Box>
+    </SettingsPageConranier>
+
+  );
+}
+
+export default SettingsFeed;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Settings_SettingsHeader_SettingsHeader.jsx.html b/docs/components_Settings_SettingsHeader_SettingsHeader.jsx.html new file mode 100644 index 00000000..c262bd29 --- /dev/null +++ b/docs/components_Settings_SettingsHeader_SettingsHeader.jsx.html @@ -0,0 +1,98 @@ + + + + + JSDoc: Source: components/Settings/SettingsHeader/SettingsHeader.jsx + + + + + + + + + + +
+ +

Source: components/Settings/SettingsHeader/SettingsHeader.jsx

+ + + + + + +
+
+
import { useEffect, useState } from 'react';
+import { useNavigate } from 'react-router-dom';
+import {
+  HeaderContiner, TabsContiner, Tab, TabText, Nav,
+} from './styles';
+/**
+ * - SettingsHeader
+ * - Head of Settings
+ *  @component
+ */
+function SettingsHeader() {
+  const [navigate, setNavigate] = useState('/settings');
+  const history = useNavigate();
+  useEffect(() => {
+    setNavigate(window.location.pathname);
+  }, [history]);
+  return (
+    <section data-testid="settings-header">
+
+      <HeaderContiner id="settings">User settings</HeaderContiner>
+
+      <Nav>
+        <TabsContiner>
+          <Tab
+            active={navigate === '/settings' || navigate === '/settings/account'}
+            to="/settings/account"
+          >
+            <TabText>Account</TabText>
+          </Tab>
+          <Tab to="/settings/profile" active={navigate === '/settings/profile'}>
+            <TabText>
+              Profile
+            </TabText>
+          </Tab>
+          <Tab to="/settings/privacy" active={window.location.pathname === '/settings/privacy'}>
+            <TabText>Safety & privacy</TabText>
+          </Tab>
+          <Tab to="/settings/feed" active={window.location.pathname === '/settings/feed'}>
+            <TabText> Feed Settings</TabText>
+          </Tab>
+        </TabsContiner>
+      </Nav>
+    </section>
+  );
+}
+
+export default SettingsHeader;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Settings_SettingsPrivacy_SettingsPrivacy.jsx.html b/docs/components_Settings_SettingsPrivacy_SettingsPrivacy.jsx.html new file mode 100644 index 00000000..a1b9c963 --- /dev/null +++ b/docs/components_Settings_SettingsPrivacy_SettingsPrivacy.jsx.html @@ -0,0 +1,146 @@ + + + + + JSDoc: Source: components/Settings/SettingsPrivacy/SettingsPrivacy.jsx + + + + + + + + + + +
+ +

Source: components/Settings/SettingsPrivacy/SettingsPrivacy.jsx

+ + + + + + +
+
+
import { Box } from '@mui/system';
+import { useEffect, useState } from 'react';
+import { useNavigate } from 'react-router-dom';
+import { useAlert } from 'react-alert';
+import {
+  Header, Content, ContentHeader,
+  SettingsPageConranier, SubHeader, ContentSubHeader, Text,
+} from '../styles';
+import { privacyFetch, blockuser } from './settingsPrivacyServer';
+import {
+  AddBlock, AddButton, RedditTextField, BlocekConataier, ImageBlock,
+  BlocekInfo,
+} from './styles';
+/**
+ * - SettingsPrivacy
+ * - Edit block list in Settings page
+ *  @component
+ */
+function SettingsPrivacy() {
+  const alert = useAlert();
+
+  const [name, setName] = useState('');
+  const [blocked, setBloked] = useState([]);
+  const [data] = privacyFetch();
+  const navigate = useNavigate();
+
+  useEffect(() => {
+    setBloked(data);
+    console.log(data);
+  }, [data]);
+  const actionUSer = async (nameUser, action) => {
+    if (nameUser !== '') {
+      const [text, type] = await blockuser(nameUser, action);
+      if (text !== 'Operation done successfully') {
+      // setMessage(text);
+      // setStats(type);
+      //  setOpenAlert(true);
+        if (action === 'block_user') {
+          let list = blocked;
+          list = list.concat({ profilePicture: 'https://i.pinimg.com/474x/eb/c8/82/ebc882ee454681ad38fcf9380342bc03.jpg', userName: nameUser });
+          console.log(list);
+          setBloked(list);
+        } else {
+          let list = blocked;
+          list = list.filter((e) => (e.userName !== nameUser));
+          setBloked(list);
+        }
+        alert.show({ text, type });
+      }
+    }
+  };
+  return (
+    <SettingsPageConranier data-testid="settings-privacy">
+      <Box sx={{ maxWidth: '688px', flex: '1 1 auto' }}>
+        <Header>Safety & Privacy</Header>
+        <ContentSubHeader sx={{ marginBottom: '32px' }}>Manage how we use data to personalize your Reddit experience, and control how other redditors interact with you.</ContentSubHeader>
+        <SubHeader>SAFETY</SubHeader>
+        <Text>
+          <Content>
+            <ContentHeader>
+              People Youโ€™ve Blocked
+            </ContentHeader>
+            <ContentSubHeader>
+              Blocked people canโ€™t send you chat requests or private messages.
+            </ContentSubHeader>
+          </Content>
+          <AddBlock>
+            <RedditTextField
+              value={name}
+              label="BLOCK NEW USER"
+              variant="filled"
+              type="text"
+              onChange={(e) => { setName(e.currentTarget.value.trim()); }}
+            />
+            <AddButton active={name.length > 0} onClick={() => { actionUSer(name, 'block_user'); }}>ADD</AddButton>
+          </AddBlock>
+        </Text>
+        {
+          blocked?.map((e) => (
+
+            <BlocekConataier>
+              <BlocekInfo onClick={() => { navigate(`/user/${e.userName}`); }}>
+                <ImageBlock src={e.profilePicture} />
+                { e.userName }
+              </BlocekInfo>
+              <AddButton active onClick={() => { actionUSer(e.userName, 'unblock_user'); }}>Remove</AddButton>
+            </BlocekConataier>
+          ))
+        }
+      </Box>
+    </SettingsPageConranier>
+  );
+}
+
+export default SettingsPrivacy;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Settings_SettingsProfile_ProfileImage_ProfileImage.jsx.html b/docs/components_Settings_SettingsProfile_ProfileImage_ProfileImage.jsx.html new file mode 100644 index 00000000..3c3fb33e --- /dev/null +++ b/docs/components_Settings_SettingsProfile_ProfileImage_ProfileImage.jsx.html @@ -0,0 +1,188 @@ + + + + + JSDoc: Source: components/Settings/SettingsProfile/ProfileImage/ProfileImage.jsx + + + + + + + + + + +
+ +

Source: components/Settings/SettingsProfile/ProfileImage/ProfileImage.jsx

+ + + + + + +
+
+
/* eslint-disable no-restricted-syntax */
+import { Box } from '@mui/material';
+import AddAPhotoOutlinedIcon from '@mui/icons-material/AddAPhotoOutlined';
+import { useContext, useEffect } from 'react';
+import {
+  ContentSubHeader, ContentHeader, Content, Text, SubHeader,
+} from '../../styles';
+import { ProfilePic, AddPhoto } from './styles';
+import { SettingsContext } from '../../../../contexts/SettingsProvider';
+import { imagePost } from '../../settingsServer';
+
+/**
+ * - ProfileImage
+ * - Edit Image and Banner in Seetings Page
+ *  @component
+ */
+
+function ProfileImage() {
+  const {
+    prefs, setPrefs,
+  } = useContext(SettingsContext);
+  useEffect(() => {
+    console.log(prefs);
+  }, [prefs]);
+  const onFileChange = async (event, type) => {
+    const file = event.target.files[0];
+    console.log(event.target.files[0]);
+    if (event.target && event.target.files[0]) {
+      const formData = new FormData();
+
+      formData.append('type', type);
+      formData.append('file', event.target.files[0]);
+      console.log(formData);
+      console.log(event.target.files[0]);
+      for (const pair of formData.entries()) {
+        console.log(`${pair[0]}, ${pair[1]}`);
+      }
+
+      imagePost(formData);
+
+      const reader = new FileReader();
+      reader.onload = () => {
+        if (reader.readyState === 2) {
+          if (file) {
+            if (type === 'profileBackground') {
+              setPrefs((oldPrefs) => ({ ...oldPrefs, profileBackground: reader.result }));
+            } else {
+              setPrefs((oldPrefs) => ({ ...oldPrefs, profilePicture: reader.result }));
+            }
+          }
+        }
+      };
+      reader.readAsDataURL(event.target.files[0]);
+    }
+  };
+
+  return (
+    <>
+      <SubHeader>
+        IMAGES
+      </SubHeader>
+      <Text>
+        <Content>
+          <ContentHeader>
+            Avatar and banner image
+          </ContentHeader>
+          <ContentSubHeader>
+            Images must be .png or .jpg format
+          </ContentSubHeader>
+        </Content>
+        <Box sx={{
+          display: 'flex',
+          '@media screen and (max-width: 626px)': {
+            flexDirection: 'column',
+          },
+        }}
+        >
+          <Box sx={{ display: 'flex', marginRight: '18px' }}>
+            <Box sx={{
+              position: 'relative',
+            }}
+            >
+              <ProfilePic width="120px" height="120px" src={prefs?.profilePicture} alt="user photo" />
+
+              <AddPhoto
+                sx={{
+                  border: (theme) => `thin solid ${theme.palette.primary?.main}`,
+                  position: 'absolute',
+                  right: '5%',
+                  top: '65%',
+                }}
+              >
+                <label type="file" htmlFor="profilePicture">
+                  <input style={{ display: 'none' }} type="file" name="image-upload" accept=".png, .jpg, .jpeg" id="profilePicture" onChange={(e) => { onFileChange(e, 'profilePicture'); }} />
+                  <AddAPhotoOutlinedIcon sx={{ cursor: 'pointer', marginTop: '5px' }} color="primary" fontSize="small" />
+                </label>
+              </AddPhoto>
+
+            </Box>
+          </Box>
+          <Box sx={{ display: 'flex' }}>
+            <Box sx={{
+              position: 'relative',
+            }}
+            >
+              <ProfilePic
+                sx={{
+                  '@media screen and (max-width: 626px)': {
+                    width: '250px',
+                  },
+                }}
+                width="412px"
+                height="120px"
+                src={prefs?.profileBackground}
+                alt="user photo"
+              />
+              <AddPhoto sx={{
+                border: (theme) => `thin solid ${theme.palette.primary?.main}`,
+                position: 'absolute',
+                right: '5%',
+                top: '65%',
+              }}
+              >
+                <label type="file" htmlFor="profileBackground">
+                  <input style={{ display: 'none' }} type="file" name="image-upload" accept=".png, .jpg, .jpeg" id="profileBackground" onChange={(e) => { onFileChange(e, 'profileBackground'); }} />
+                  <AddAPhotoOutlinedIcon sx={{ cursor: 'pointer', marginTop: '5px' }} color="primary" fontSize="small" />
+                </label>
+              </AddPhoto>
+            </Box>
+          </Box>
+        </Box>
+      </Text>
+    </>
+  );
+}
+
+export default ProfileImage;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Settings_SettingsProfile_ProfileInoformation_ProfileInoformation.jsx.html b/docs/components_Settings_SettingsProfile_ProfileInoformation_ProfileInoformation.jsx.html new file mode 100644 index 00000000..5527771c --- /dev/null +++ b/docs/components_Settings_SettingsProfile_ProfileInoformation_ProfileInoformation.jsx.html @@ -0,0 +1,152 @@ + + + + + JSDoc: Source: components/Settings/SettingsProfile/ProfileInoformation/ProfileInoformation.jsx + + + + + + + + + + +
+ +

Source: components/Settings/SettingsProfile/ProfileInoformation/ProfileInoformation.jsx

+ + + + + + +
+
+
import { useState, useContext, useEffect } from 'react';
+
+import { useAlert } from 'react-alert';
+import {
+  ContentSubHeader, ContentHeader, Content, Text,
+} from '../../styles';
+import {
+  DisplayName, About,
+} from './styles';
+import { SettingsContext } from '../../../../contexts/SettingsProvider';
+
+import { settingsPost } from '../../settingsServer';
+import SocialLinksSettings from './SocialLinksSettings/SocialLinksSettings';
+/**
+ * - ProfileInoformation
+ * - Edit Display name  and About people in Seetings Page
+ *  @param {Object} prefs - prefs of user
+ *  @property {function} setPrefs set prefs of user
+ *  @property {String} name name of user
+ *  @property {String} about description of user
+ *  @component
+ */
+function ProfileInoformation() {
+  const {
+    prefs, setPrefs,
+  } = useContext(SettingsContext);
+  const alert = useAlert();
+  const [name, setName] = useState('');
+  const [about, setAbout] = useState('');
+  useEffect(() => { console.log(prefs); }, [prefs]);
+
+  useEffect(() => {
+    setName(prefs?.displayName);
+    setAbout(prefs?.description);
+  }, [prefs]);
+
+  const handleDisplayName = async () => {
+    setPrefs((oldPrefs) => ({ ...oldPrefs, displayName: name }));
+    const [text, type] = await settingsPost({ ...prefs, displayName: name });
+    if (text !== '') {
+      alert.show({ text, type });
+    }
+  };
+  const handleInfo = async () => {
+    setPrefs((oldPrefs) => ({ ...oldPrefs, description: about }));
+    const [text, type] = await settingsPost({ ...prefs, description: about });
+    if (text !== '') {
+      alert.show({ text, type });
+    }
+  };
+
+  return (
+    <>
+      <Text>
+        <Content>
+          <ContentHeader>
+            Display name (optional)
+          </ContentHeader>
+          <ContentSubHeader>
+            Set a display name. This does not change your username.
+          </ContentSubHeader>
+        </Content>
+        <DisplayName
+          onBlur={() => { handleDisplayName(); }}
+          value={name}
+          maxLength={30}
+          onChange={(e) => { setName(e.target.value); }}
+        />
+        <ContentSubHeader sx={{ color: (30 - ((name) ? name.length : 0) === 0) ? 'red' : '#7c7c7c' }}>
+          {30 - ((name) ? name.length : 0)}
+          {' '}
+          Character remaining
+        </ContentSubHeader>
+      </Text>
+      <Text>
+        <Content>
+          <ContentHeader>
+            About (optional)
+          </ContentHeader>
+          <ContentSubHeader>
+            A brief description of yourself shown on your profile.
+          </ContentSubHeader>
+        </Content>
+        <About
+          onBlur={() => { handleInfo(); }}
+          value={about}
+          maxLength={200}
+          onChange={(e) => { setAbout(e.target.value); }}
+        />
+        <ContentSubHeader sx={{ color: (200 - ((about) ? about.length : 0) === 0) ? 'red' : '#7c7c7c' }}>
+          {200 - ((about) ? about.length : 0) }
+          {' '}
+          Character remaining
+        </ContentSubHeader>
+      </Text>
+      <SocialLinksSettings />
+    </>
+  );
+}
+
+export default ProfileInoformation;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Settings_SettingsProfile_ProfileInoformation_SocialLinksSettings_SocialLinksSettings.jsx.html b/docs/components_Settings_SettingsProfile_ProfileInoformation_SocialLinksSettings_SocialLinksSettings.jsx.html new file mode 100644 index 00000000..cc41c3db --- /dev/null +++ b/docs/components_Settings_SettingsProfile_ProfileInoformation_SocialLinksSettings_SocialLinksSettings.jsx.html @@ -0,0 +1,151 @@ + + + + + JSDoc: Source: components/Settings/SettingsProfile/ProfileInoformation/SocialLinksSettings/SocialLinksSettings.jsx + + + + + + + + + + +
+ +

Source: components/Settings/SettingsProfile/ProfileInoformation/SocialLinksSettings/SocialLinksSettings.jsx

+ + + + + + +
+
+
import { useState, useContext } from 'react';
+
+import AddIcon from '@mui/icons-material/Add';
+import { Box } from '@mui/system';
+import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
+import CreateSocail from '../../../../SocialLinks/SocialLinks';
+import { SettingsContext } from '../../../../../contexts/SettingsProvider';
+import { socialDelete } from './SocialLinksSettingsServer';
+import {
+  ContentSubHeader, ContentHeader, Content, Text,
+} from '../../../styles';
+import {
+  AddSocialLinks, BootstrapDialog, Social, PlatformIcon,
+} from './styles';
+/**
+ * - ProfileInoformation
+ * - Edit Display name  and About people in Seetings Page
+ *  @param {Object} prefs - prefs of user
+ *  @param {function} setPrefs set prefs of user
+ *  @property {Boolean} open Boolean to open or close popup
+ *  @property {function} handleDelete function to delete social link
+ *  @component
+ */
+function SocialLinksSettings() {
+  const {
+    prefs, setPrefs,
+  } = useContext(SettingsContext);
+  const [open, setOpen] = useState(false);
+  const [settings, setSettings] = useState(false);
+  const [link, setLink] = useState();
+  const openSocial = () => {
+    console.log(prefs?.socialLinks.length);
+    if (prefs?.socialLinks.length < 5) { setOpen(true); }
+  };
+  const handleDelete = (e, link) => {
+    const newSocial = prefs?.socialLinks.filter((e) => e._id !== link._id);
+    setPrefs((oldPrefs) => ({ ...oldPrefs, socialLinks: newSocial }));
+    socialDelete(link._id);
+    e.stopPropagation();
+  };
+  return (
+    <>
+      <Text>
+        <Content>
+          <ContentHeader>
+            Social links (5 max)
+          </ContentHeader>
+          <ContentSubHeader>
+            People who visit your profile will see your social links.
+          </ContentSubHeader>
+        </Content>
+        <Box sx={{ display: 'flex', flexWrap: 'wrap' }}>
+          {prefs?.socialLinks.map((link, index) => (
+            <Social
+              key={`${index + 0}`}
+              onClick={() => {
+                setOpen(true);
+                setLink(link);
+                setSettings(true);
+              }}
+            >
+              <PlatformIcon src={link?.social?.icon} />
+              { link?.displayText }
+              <CancelOutlinedIcon onClick={(e) => { handleDelete(e, link); }} />
+            </Social>
+          )) }
+        </Box>
+        <AddSocialLinks lenght={prefs?.socialLinks.length < 5} onClick={openSocial}>
+          <Box sx={{ display: 'flex', alignItems: 'center' }}>
+            <AddIcon />
+            Add social link
+          </Box>
+        </AddSocialLinks>
+      </Text>
+      {/* popup component to add social link */}
+      <BootstrapDialog
+        onClose={(event, reason) => {
+          if (reason !== 'backdropClick' && reason !== 'escapeKeyDown') {
+            setOpen(false);
+          }
+        }}
+        aria-labelledby="customized-dialog-title"
+        open={open}
+        keepMounted
+      >
+        <CreateSocail
+          link={link}
+          settings={settings}
+          onClose={(event, reason) => {
+            if (reason !== 'backdropClick' && reason !== 'escapeKeyDown') {
+              setOpen(false);
+              setSettings(false);
+            }
+          }}
+        />
+      </BootstrapDialog>
+    </>
+  );
+}
+export default SocialLinksSettings;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Settings_SettingsProfile_ProfileInoformation_SocialLinksSettings_SocialLinksSettingsServer.js.html b/docs/components_Settings_SettingsProfile_ProfileInoformation_SocialLinksSettings_SocialLinksSettingsServer.js.html new file mode 100644 index 00000000..de8e7857 --- /dev/null +++ b/docs/components_Settings_SettingsProfile_ProfileInoformation_SocialLinksSettings_SocialLinksSettingsServer.js.html @@ -0,0 +1,68 @@ + + + + + JSDoc: Source: components/Settings/SettingsProfile/ProfileInoformation/SocialLinksSettings/SocialLinksSettingsServer.js + + + + + + + + + + +
+ +

Source: components/Settings/SettingsProfile/ProfileInoformation/SocialLinksSettings/SocialLinksSettingsServer.js

+ + + + + + +
+
+
import axios from '../../../../../services/instance';
+import { redirectLogin } from '../../../../../utils/Redirect';
+/**
+ * - settings Post data prefs
+ */
+export const socialDelete = async (id) => {
+  const api = `/users/social_links/${id}`;
+  await axios.delete(`${api}`)
+    .then((response) => {
+      console.log(response);
+    }).catch((error) => {
+      if (error?.response.status === 401) {
+        redirectLogin();
+      }
+      console.log(error);
+    });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Settings_SettingsProfile_SettingsProfile.jsx.html b/docs/components_Settings_SettingsProfile_SettingsProfile.jsx.html new file mode 100644 index 00000000..1195f9c0 --- /dev/null +++ b/docs/components_Settings_SettingsProfile_SettingsProfile.jsx.html @@ -0,0 +1,140 @@ + + + + + JSDoc: Source: components/Settings/SettingsProfile/SettingsProfile.jsx + + + + + + + + + + +
+ +

Source: components/Settings/SettingsProfile/SettingsProfile.jsx

+ + + + + + +
+
+
import { Box } from '@mui/system';
+import { Switch } from '@mui/material';
+import { useEffect, useState } from 'react';
+import { useAlert } from 'react-alert';
+import {
+  AntSwitch, ContentSubHeader, ContentHeader, Content, Button, Header,
+  SettingsPageConranier, SubHeader,
+} from '../styles';
+import ProfileInoformation from './ProfileInoformation/ProfileInoformation';
+import ProfileImage from './ProfileImage/ProfileImage';
+import SettingsProvider from '../../../contexts/SettingsProvider';
+import { settingsPost, settingsFetch } from '../settingsServer';
+
+/**
+ * - SettingsProfile
+ * - Edit NSFW and Allow people to follow you in Seetings Page
+ *  @property {String} data data from fetch
+ *  @property {Object} prefs prefs of user
+ *  @component
+ */
+function SettingsProfile() {
+  const alert = useAlert();
+  const [prefs, setPrefs] = useState();
+  const [data] = settingsFetch();
+  useEffect(() => {
+    setPrefs(data?.prefs);
+  }, [data]);
+  const handleNSFW = async () => {
+    setPrefs((oldPrefs) => ({ ...oldPrefs, nsfw: !oldPrefs.nsfw }));
+    const [text, type] = await settingsPost({ ...prefs, nsfw: !prefs?.nsfw });
+    if (text !== '') {
+      alert.show({ text, type });
+    }
+  };
+  const handleCanbeFollowed = async () => {
+    setPrefs((oldPrefs) => ({ ...oldPrefs, canbeFollowed: !oldPrefs.canbeFollowed }));
+    const [text, type] = await settingsPost({ ...prefs, canbeFollowed: !prefs?.canbeFollowed });
+    if (text !== '') {
+      alert.show({ text, type });
+    }
+  };
+  return (
+
+    <SettingsPageConranier data-testid="settings-profile">
+      <Box sx={{ maxWidth: '688px', flex: '1 1 auto' }}>
+        <Header>Customize profile</Header>
+        <SubHeader>PROFILE INFORMATION</SubHeader>
+        <SettingsProvider prefs={prefs} setPrefs={setPrefs}>
+          <ProfileInoformation />
+        </SettingsProvider>
+        <SettingsProvider prefs={prefs} setPrefs={setPrefs}>
+          <ProfileImage />
+        </SettingsProvider>
+        <SubHeader>PROFILE CATEGORY</SubHeader>
+        <Button>
+          <Content>
+            <ContentHeader>
+              NSFW
+            </ContentHeader>
+            <ContentSubHeader>
+              This content is NSFW (may contain nudity, pornography, profanity or inappropriate content for those under 18)
+            </ContentSubHeader>
+          </Content>
+          <AntSwitch onClick={() => { handleNSFW(); }}>
+            <Switch checked={prefs?.nsfw || false} />
+          </AntSwitch>
+        </Button>
+        <SubHeader>ADVANCED</SubHeader>
+        <Button>
+          <Content>
+            <ContentHeader>
+              Allow people to follow you
+            </ContentHeader>
+            <ContentSubHeader>
+              Followers will be notified about posts you make to your profile and see them in their home feed.
+            </ContentSubHeader>
+          </Content>
+          <AntSwitch onClick={() => { handleCanbeFollowed(); }}>
+            <Switch checked={prefs?.canbeFollowed || false} />
+
+          </AntSwitch>
+        </Button>
+      </Box>
+    </SettingsPageConranier>
+
+  );
+}
+
+export default SettingsProfile;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_Settings_settingsServer.js.html b/docs/components_Settings_settingsServer.js.html new file mode 100644 index 00000000..db4a7b05 --- /dev/null +++ b/docs/components_Settings_settingsServer.js.html @@ -0,0 +1,111 @@ + + + + + JSDoc: Source: components/Settings/settingsServer.js + + + + + + + + + + +
+ +

Source: components/Settings/settingsServer.js

+ + + + + + +
+
+
import axios from '../../services/instance';
+import { redirectLogin } from '../../utils/Redirect';
+import useFetch from '../../hooks/useFetch';
+/**
+ * - settings Post data prefs
+ */
+export const settingsPost = async (prefs) => {
+  const api = '/users/me/prefs';
+  let message = '';
+  let flag = 'error';
+  console.log(prefs);
+  await axios.patch(`${api}`, prefs)
+    .then((response) => {
+      console.log(response);
+
+      flag = 'success';
+      message = 'operation done successfully';
+    }).catch((error) => {
+      console.log(error);
+      message = 'Operation failed';
+
+      if (error.message !== 'Network Error') {
+        if (error?.response.status === 401) {
+          redirectLogin();
+        } else {
+          message = 'Operation failed';
+        }
+      }
+    });
+  return [message, flag];
+};
+export const settingsFetch = () => {
+  const api = '/users/me/prefs';
+  const [data, dataError, statusCode] = useFetch(api);
+  console.log('www', data);
+  if (statusCode === 401) {
+    redirectLogin();
+  }
+  if (dataError) {
+    console.log(dataError);
+  }
+  const prefs = data;
+  return [prefs];
+};
+
+export const imagePost = async (data) => {
+  const api = '/users/images';
+  console.log('hh', data);
+  await axios.post(`${api}`, data, { headers: { 'Content-Type': 'multipart/form-data' } })
+    .then((response) => {
+      console.log(response);
+    }).catch((error) => {
+      console.log(error);
+      if (error.message !== 'Network Error') {
+        if (error?.response.status === 401) {
+          redirectLogin();
+        }
+      }
+    });
+};
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SideBar_SideBar.jsx.html b/docs/components_SideBar_SideBar.jsx.html new file mode 100644 index 00000000..716d8029 --- /dev/null +++ b/docs/components_SideBar_SideBar.jsx.html @@ -0,0 +1,70 @@ + + + + + JSDoc: Source: components/SideBar/SideBar.jsx + + + + + + + + + + +
+ +

Source: components/SideBar/SideBar.jsx

+ + + + + + +
+
+
import { SideBarContainer } from './styles';
+/**
+ * This component works as a container for the right half components
+ * like communities in home page
+ *
+ * @component SideBar
+ * @property {React.Component} children -Components which will be wrapped in sidebar
+ * @returns {React.Component} Container represents its children
+ */
+
+function SideBar({ children, responsive }) {
+  return (
+    <SideBarContainer responsive={responsive}>
+      {children}
+    </SideBarContainer>
+  );
+}
+
+export default SideBar;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SocialLinks_SocialLinks.jsx.html b/docs/components_SocialLinks_SocialLinks.jsx.html new file mode 100644 index 00000000..d4b600c5 --- /dev/null +++ b/docs/components_SocialLinks_SocialLinks.jsx.html @@ -0,0 +1,245 @@ + + + + + JSDoc: Source: components/SocialLinks/SocialLinks.jsx + + + + + + + + + + +
+ +

Source: components/SocialLinks/SocialLinks.jsx

+ + + + + + +
+
+
import DialogTitle from '@mui/material/DialogTitle';
+import DialogContent from '@mui/material/DialogContent';
+import IconButton from '@mui/material/IconButton';
+import CloseIcon from '@mui/icons-material/Close';
+import { useState, useEffect } from 'react';
+import ArrowBackIcon from '@mui/icons-material/ArrowBack';
+import { Typography } from '@mui/material';
+import { allSocialLinks, postSocialLink } from './socialLinksServer';
+import {
+  InputBox, SaveBtn, Text, PlatformIcon,
+} from './styles';
+/**
+ *@component
+ * @property {Array} links - Array of links
+ * @property {Boolean} openDialog2 - bool to choose which window open
+ * @property {Object} platform - data of plateform choose
+ * @property {Boolean} condition - condition if valid we submit or not
+ * @property {string} text - url or  user name
+ * @property {Boolean} error - true if we have invalid domin or username
+ * @property {string} msg - massage if we have error
+ * @property {Boolean} url - true if plate form have link and display name
+ * @property {Boolean} edit - true if it's first time to edit text
+ * @property {string} title - title of link
+ * @property {Function} handleOpenPlatform - function to open window to edit data platedform
+ * @property {Function} handleClose -  function to close window to edit data platedform
+ * @property {Function} checkSubmission - function to check data before submit
+ * @property {Function} handelchange - function to handle input from user
+ *  @param {Function} onClose - function when close window
+ *  @param {Boolean} settings - bool too know if we in settings page or not
+ *  @param {Object} link - data of plateform we choose in settings
+ */
+function SocialLinks({
+  onClose, settings, link,
+}) {
+  const [links] = allSocialLinks();
+  const [openDialog2, setDialog2] = useState(false);
+  const [platform, setPlatform] = useState(null);
+  const [condition, setCondition] = useState(false);
+  const [text, setText] = useState('');
+  const [error, setError] = useState(false);
+  const [msg, setMsg] = useState('');
+  const [url, setUrl] = useState(false);
+  const [edit, setEdit] = useState(true);
+  const [title, setTitle] = useState('');
+
+  useEffect(() => {
+    if (settings) {
+      setDialog2(true);
+      setPlatform(link?.social);
+      if (link?.social.placeholderLink.includes('https://')) {
+        setText(link?.userLink);
+        setTitle(link?.displayText);
+      } else {
+        let textlink = link?.userLink.replace(link?.social.baseLink, '');
+        textlink = textlink.replace(/^/, link?.social.check);
+        console.log(textlink);
+        console.log(link?.userLink);
+        setText(textlink);
+        setTitle(link?.displayText);
+      }
+      setUrl(link?.social.placeholderLink.includes('https://'));
+    }
+  }, [settings]);
+
+  useEffect(() => {
+    if (url) {
+      if (text.length >= 1 && title.length > 0) {
+        setCondition(true);
+      } else { setCondition(false); }
+    } else if (text.length >= 1) { setCondition(true); } else { setCondition(false); }
+  }, [title, text]);
+
+  const handleOpenPlatform = (link) => {
+    setDialog2(true);
+    setPlatform(link);
+    setEdit(true);
+    setUrl(link?.placeholderLink.includes('https://'));
+  };
+
+  const handleClose = () => {
+    setError(false);
+    setText('');
+    setTitle('');
+    setDialog2(false);
+    if (settings) {
+      onClose();
+    }
+  };
+
+  const checkSubmission = () => {
+    if (!(text.includes(platform?.check) && text.length > 1)) {
+      setError(true);
+      if (url) {
+        setMsg('Invalid domin');
+      } else {
+        setMsg('Username is not valid');
+      }
+    } else {
+      setError(false);
+      if (url) {
+        postSocialLink([text, title, platform?._id], settings, link);
+      } else {
+        postSocialLink([platform.baseLink + text.replace(platform?.check, ''), text.replace(platform?.check, ''), platform?._id], settings, link);
+      }
+      onClose();
+    }
+  };
+  const handelchange = (e) => {
+    if (!settings && edit) {
+      setText(platform.check + e.target.value.trim());
+      setEdit(false);
+    } else {
+      setText(e.target.value.trim());
+    }
+  };
+  return (
+    !openDialog2 ? (
+      <>
+        <DialogTitle sx={{
+          m: 0, p: 2, display: 'flex', justifyContent: 'center', fontWeight: 700,
+        }}
+        >
+          Add Social Link
+          {onClose ? (
+            <IconButton
+              aria-label="close"
+              onClick={onClose}
+              sx={{
+                position: 'absolute',
+                right: 8,
+                top: 8,
+                color: (theme) => theme.palette.grey[500],
+              }}
+            >
+              <CloseIcon />
+            </IconButton>
+          ) : null}
+        </DialogTitle>
+        <DialogContent
+          dividers
+          sx={{
+            display: 'flex',
+            flexDirection: 'row',
+            flexWrap: 'wrap',
+          }}
+        >
+          {links?.map((link, index) => (
+            <Text key={`${index + 0}`} onClick={() => handleOpenPlatform(link)}>
+              <PlatformIcon src={link?.icon} />
+              {link?.type}
+            </Text>
+          )) }
+        </DialogContent>
+      </>
+    ) : (
+      <>
+        <DialogTitle sx={{
+          m: 0, p: 2, display: 'flex', justifyContent: 'space-between',
+        }}
+        >
+          <IconButton
+            onClick={handleClose}
+            sx={{
+              color: '#878a8c',
+            }}
+          >
+            <ArrowBackIcon />
+          </IconButton>
+          <Typography
+            variant="h6"
+            sx={{
+              display: 'flex', alignItems: 'center',
+            }}
+          >
+            Add Social Link
+          </Typography>
+          <SaveBtn variant="contained" condition={condition.toString()} onClick={() => checkSubmission()}>Save</SaveBtn>
+        </DialogTitle>
+        <DialogContent dividers>
+          <Text>
+            <PlatformIcon src={platform?.icon} />
+            {platform?.type}
+          </Text>
+          { url
+              && <InputBox type="text" value={title} placeholder="Display Text" onChange={(e) => { setTitle(e.target.value); }} />}
+          <InputBox type="text" value={text} placeholder={platform?.placeholderLink} onChange={(e) => { handelchange(e); }} />
+          {error ? <Typography sx={{ color: 'red', marginLeft: 1 }} variant="caption">{msg}</Typography> : null}
+        </DialogContent>
+      </>
+    )
+  );
+}
+
+export default SocialLinks;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_Cover.jsx.html b/docs/components_SubReddit_Cover.jsx.html new file mode 100644 index 00000000..38887b0a --- /dev/null +++ b/docs/components_SubReddit_Cover.jsx.html @@ -0,0 +1,276 @@ + + + + + JSDoc: Source: components/SubReddit/Cover.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/Cover.jsx

+ + + + + + +
+
+
import { Box, ThemeProvider, Typography } from '@mui/material';
+import { useParams } from 'react-router-dom';
+import { useEffect, useMemo, useState } from 'react';
+import { useCookies } from 'react-cookie';
+import PostList from '../HomePage/HomePageContainer/PostList/PostList';
+import { redditCookie } from '../Authentication/authenticationServer';
+import Nsfw from '../NSFW/Nsfw';
+import FormDialog from '../HomePage/HomePageContainer/PersonalReddit/PopUpSubReddit/PopUp';
+import MainContent from '../MainContent/MainContent';
+// import PostSubreddit from '../Post/Post';
+import CreatePostInSubreddit from '../HomePage/HomePageContainer/CreatePostInHome/CreatePostInHome';
+import SideBar from './SideBar/SideBar';
+import {
+  Com, Content, Cover, Data, Desc, IconContainer, Image, Join, Logo, Namee, PostHeader, TotalHeader, JoinCommunity, NotFountImage, NotFoundBox, BackHomeButton,
+} from './style';
+// import PostsClassificationSubreddit from './PostClassificationSubreddit/PostClassification';
+import PostsClassificationSubreddit from '../HomePage/HomePageContainer/PostsClassification/PostsClassification';
+import theme2 from '../../styles/theme/layout';
+import SubredditData from './SubrridetDataServer';
+import ModeratorData from './subriddetDataModeratorServer';
+import PostsData from './subredditPostsServer';
+import PostJoin from './PostJoin';
+// import leave from './leaveServer';
+import SubredditNotification from './Notifications/SubriddetNotifications';
+import { useCreatePostInSubredditContext } from '../../contexts/CreatePostInSubredditContext';
+import cleanPage from '../../utils/cleanPage';
+/**
+ * Subreddit page
+ * @component
+ * @property  {function} redirect redirect to homepage
+ * @property  {function} createCommunity open create community form
+ * @property  {function} sendData send data to backend
+
+ * @return {React.Component} - Subreddit page
+ */
+
+function Header() {
+  const [posts, setPosts] = useState([]);
+  const [icon, setIcon] = useState();
+  const [join, setJoin] = useState('');
+  const [disc, setDisc] = useState();
+  const [createdAt, setCreatedAt] = useState();
+  const [primaryTopic, setPrimaryTopic] = useState();
+  const [topics, setTopics] = useState([]);
+  const [moderatoesName, setModeratoesName] = useState([]);
+  const [fixedName, setFixedName] = useState();
+  const [cookies, setCookies] = useCookies(['redditUser']);
+  const [username, setUserName] = useState('');
+  const [members, setMembers] = useState();
+  const [exist, setExist] = useState(true);
+  const [showPopUp, setShowPopUp] = useState(false);
+  const [rules, setRules] = useState([]);
+
+  const [nsfw, setNsfw] = useState();
+  const [userNsfw, setUserNsfw] = useState();
+  const [warning, setWarning] = useState(false);
+
+  cleanPage();
+
+  const redirect = () => {
+    window.location.pathname = '/';
+  };
+
+  const createCommunity = async () => {
+    await setShowPopUp(true);
+    const ele = document.getElementById('popup-form-button');
+    ele.click();
+  };
+  useEffect(() => {
+    redditCookie(setCookies);
+  }, []);
+
+  useEffect(() => {
+    setUserName(cookies.redditUser?.userName);
+    setUserNsfw(cookies.redditUser?.adultContent);
+  }, [cookies]);
+
+  const { Name, postClass } = useParams();
+
+  const [data, dataError, statusCode] = SubredditData(Name);
+  const { setSubredditId, setSubredditName, setSubredditIcon } = useCreatePostInSubredditContext();
+  const value = useMemo(() => ({ data, dataError }), [data, dataError]);
+  console.log(value);
+
+  const [data3, dataError3] = PostsData(Name, postClass);
+  console.log(dataError3);
+  useEffect(() => {
+    if (statusCode === 404) {
+      setExist(false);
+    }
+    setIcon(data?.icon);
+    setRules(data?.rules);
+    setDisc(data?.description);
+    setTopics(data?.topics);
+    setPrimaryTopic(data?.primaryTopic);
+    setCreatedAt(data?.createdAt);
+    setModeratoesName(data?.moderators);
+    setFixedName(data?.fixedName);
+    setMembers(data?.membersCount);
+    setSubredditId(data?.id);
+    setSubredditName(Name);
+    setSubredditIcon(data?.icon);
+    console.log(data?._id);
+    setPosts(data3?.data);
+    console.log(data3?.data);
+    // join and comment another endpoint line 95
+    // setJoin(data?.isJoined);
+  }, [data, postClass, data3, statusCode]);
+
+  useEffect(() => {
+    setNsfw(data?.nsfw);
+    if (userNsfw === false && nsfw === true) {
+      setWarning(true);
+    } else {
+      setWarning(false);
+    }
+    console.log(warning);
+  }, [data, nsfw, userNsfw]);
+
+  // fetch data of communities i am a moderator of
+
+  const [data2, dataError2] = ModeratorData();
+
+  const value2 = useMemo(() => ({ data2, dataError2 }), [data2, dataError2]);
+  console.log(value2);
+
+  useEffect(() => {
+    console.log(dataError2);
+
+    if ((data2?.filter((e) => e?.fixedName === Name?.toString()))?.length > 0) {
+      setJoin(true);
+    } else {
+      setJoin(false);
+    }
+  }, [data2, username]);
+
+  // subscribr or unsubscribe
+  const sendData = (b) => {
+    PostJoin(`/subreddits/${Name}/subscribe`, b);
+    // leave(Name, { isJoined: b });
+  };
+  // const leaveCommunity = (b) => {
+  //   leave(Name, { isJoined: b });
+  // };
+  return (
+    exist ? (
+      warning ? (
+        <Nsfw handleWarning={() => { setWarning(false); }} />
+      )
+        : (
+          <>
+            <Cover />
+            <Logo>
+              <IconContainer>
+                <Data>
+                  <Image src={icon} />
+                  <Content>
+                    <Desc>
+                      <Namee>
+                        r/
+                        {Name}
+                      </Namee>
+                      <Com>
+                        r/
+                        {fixedName}
+                      </Com>
+                    </Desc>
+                    <Box sx={{ display: 'flex' }}>
+                      {!join
+                && <JoinCommunity onClick={() => { setJoin(true); sendData('sub'); }}>Join</JoinCommunity>}
+                      {join
+                && (
+                <>
+                  <Join onClick={() => { setJoin(false); sendData('unsub'); }} onMouseEnter={(e) => { e.target.innerHTML = 'Leave'; }} onMouseLeave={(e) => { e.target.innerHTML = 'Joined'; }}>Joined</Join>
+
+                  <SubredditNotification />
+                </>
+                )}
+
+                    </Box>
+                  </Content>
+                </Data>
+                <PostHeader>Posts</PostHeader>
+              </IconContainer>
+            </Logo>
+            <TotalHeader>
+              <Box sx={{
+                display: 'flex',
+                flexDirection: 'row',
+                margin: '0 auto',
+                '@media screen and (max-width: 435px)': {
+                  width: '100%',
+                },
+              }}
+              >
+                <MainContent width={640}>
+                  <ThemeProvider theme={theme2}>
+                    <CreatePostInSubreddit subredditName={Name} />
+                  </ThemeProvider>
+                  <PostsClassificationSubreddit subredditName={Name} />
+                  {posts
+                  && <PostList posts={posts} subredit />}
+                </MainContent>
+                <SideBar rules={rules} members={members} Name={Name} username={username} topics={topics} disc={disc} primaryTopic={primaryTopic} createdAt={createdAt} moderatoesName={moderatoesName} />
+              </Box>
+            </TotalHeader>
+
+          </>
+        )
+    )
+      : (
+        <NotFoundBox>
+          <NotFountImage src="https://www.redditstatic.com/desktop2x/img/snoomoji/snoo_thoughtful.png" />
+          <Typography sx={{ fontWeight: 700, marginBottom: 2, fontSize: '18px' }}>Sorry, there arenโ€™t any communities on Reddit with that name.</Typography>
+          <Typography sx={{ marginBottom: 4, fontSize: '14px' }}>This community may have been banned or the community name is incorrect.</Typography>
+          <Box>
+            <BackHomeButton variant="outlined" onClick={createCommunity} sx={{ textTransform: 'unset' }}>Create community</BackHomeButton>
+            <BackHomeButton variant="contained" onClick={redirect}>Go Home</BackHomeButton>
+          </Box>
+          {showPopUp && <Box sx={{ display: 'absolute' }}><FormDialog display="none" /></Box>}
+        </NotFoundBox>
+      )
+  );
+}
+export default Header;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_Notifications_SubriddetNotifications.jsx.html b/docs/components_SubReddit_Notifications_SubriddetNotifications.jsx.html new file mode 100644 index 00000000..6f18ba0f --- /dev/null +++ b/docs/components_SubReddit_Notifications_SubriddetNotifications.jsx.html @@ -0,0 +1,144 @@ + + + + + JSDoc: Source: components/SubReddit/Notifications/SubriddetNotifications.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/Notifications/SubriddetNotifications.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import { useState } from 'react';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+import NotificationsIcon from '@mui/icons-material/Notifications';
+import NotificationsActiveOutlinedIcon from '@mui/icons-material/NotificationsActiveOutlined';
+import NotificationsOffOutlinedIcon from '@mui/icons-material/NotificationsOffOutlined';
+import NotificationsNoneOutlinedIcon from '@mui/icons-material/NotificationsNoneOutlined';
+import NotificationsActiveIcon from '@mui/icons-material/NotificationsActive';
+import NotificationsOffIcon from '@mui/icons-material/NotificationsOff';
+import {
+  Notification,
+  Select, SelectBox, SelectItem,
+} from './style';
+/**
+ * More icon
+ * @return {React.Component} - More icon
+ */
+export default function Notifications() {
+  const [showList1, setShowList1] = useState(false);
+  const [noti, setNoti] = useState('Low');
+
+  // toggle the list when click
+  const handleClick1 = () => {
+    setShowList1((prev) => !prev);
+  };
+
+  // handle disable the list when click away
+  const handleClickAway1 = () => {
+    setShowList1(false);
+  };
+
+  return (
+    <>
+      <Select>
+        <ClickAwayListener onClickAway={handleClickAway1}>
+          <Box data-testid="sort" sx={{ display: 'flex' }} onClick={() => { handleClick1(); }}>
+            <Notification sx={{
+              '@media screen and (max-width: 435px)': {
+                display: 'none',
+              },
+            }}
+            >
+              {noti === 'Low'
+            && <NotificationsIcon color="primary" sx={{ marginTop: '-1px' }} />}
+              {noti === 'Frequently'
+            && <NotificationsActiveIcon color="primary" sx={{ marginTop: '-1px' }} />}
+              {noti === 'Off'
+            && <NotificationsOffIcon color="primary" sx={{ marginTop: '-1px' }} />}
+            </Notification>
+          </Box>
+        </ClickAwayListener>
+      </Select>
+      {showList1 && (
+      <SelectBox data-testid="items">
+        <SelectItem onClick={() => setNoti('Low')} condition={(noti === 'Low').toString()}>
+          <NotificationsNoneOutlinedIcon
+            color={(noti === 'Low') ? 'primary' : 'black'}
+            sx={{
+              marginTop: '-1px',
+              lineHeight: 0,
+              cursor: 'pointer',
+            }}
+          />
+          Low
+        </SelectItem>
+        <SelectItem onClick={() => setNoti('Frequently')} condition={(noti === 'Frequently').toString()}>
+          <NotificationsActiveOutlinedIcon
+            color={(noti === 'Frequently') ? 'primary' : 'black'}
+            sx={{
+              marginTop: '-1px',
+              lineHeight: 0,
+              cursor: 'pointer',
+            }}
+          />
+          Frequently
+        </SelectItem>
+        <SelectItem onClick={() => setNoti('Off')} condition={(noti === 'Off').toString()}>
+          <NotificationsOffOutlinedIcon
+            color={(noti === 'Off') ? 'primary' : 'black'}
+            sx={{
+              marginTop: '-1px',
+              lineHeight: 0,
+              cursor: 'pointer',
+            }}
+          />
+          Off
+        </SelectItem>
+      </SelectBox>
+      )}
+    </>
+
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_PostJoin.js.html b/docs/components_SubReddit_PostJoin.js.html new file mode 100644 index 00000000..40393ade --- /dev/null +++ b/docs/components_SubReddit_PostJoin.js.html @@ -0,0 +1,80 @@ + + + + + JSDoc: Source: components/SubReddit/PostJoin.js + + + + + + + + + + +
+ +

Source: components/SubReddit/PostJoin.js

+ + + + + + +
+
+
import Done from '../AlertMessage';
+import axios from '../../services/instance';
+/**
+ * Join to subreddit
+ *
+ * @property {string} url - url to send data
+ * @property {string} action - sub / unsub
+
+ */
+const PostJoin = async (url, action) => {
+  // const [data, setData] = useState(null);
+  // const [error, setError] = useState(null);
+
+  await axios.post(url, [], {
+    params: {
+      action,
+    },
+  }).then((response) => {
+    console.log(response);
+    if (response?.status === 200 || response?.status === 200) {
+      Done('Done');
+    }
+    return true;
+  }).catch((error) => {
+    console.log(error);
+    return false;
+  });
+};
+export default PostJoin;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_AboutSubReddit_About.jsx.html b/docs/components_SubReddit_SideBar_AboutSubReddit_About.jsx.html new file mode 100644 index 00000000..746a06d5 --- /dev/null +++ b/docs/components_SubReddit_SideBar_AboutSubReddit_About.jsx.html @@ -0,0 +1,124 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/AboutSubReddit/About.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/AboutSubReddit/About.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined';
+import moment from 'moment/moment';
+import Sort from '../MoreIcon/More';
+
+import {
+  AboutContent, AboutCountainer, AboutDisc, AboutString, CreatedSpan,
+  More, Created, Icon, Hr, Bold, Light, SpecialBold, CustomLink, CreatPost,
+} from './style';
+/**
+ * About Section for normal user
+ * @component
+ * @return {React.Component} - About Section for normal user
+ */
+function About(props) {
+  const {
+    disc, createdAt, num, Name, createPost,
+  } = props;
+  return (
+    <>
+      <AboutCountainer>
+        <AboutString>
+          About Community
+        </AboutString>
+        <More sx={{ marginBottom: 1 }}>
+          <Sort margin={1} marginLeft="-51px" />
+        </More>
+      </AboutCountainer>
+      <AboutContent>
+        <AboutDisc>
+          {disc}
+        </AboutDisc>
+      </AboutContent>
+      <Created>
+        <Icon><EmailOutlinedIcon /></Icon>
+        <CreatedSpan>
+          Created
+          {' '}
+          {moment(createdAt).add(1, 'days').utc().format('MMMMย DD,ย YYYY')}
+        </CreatedSpan>
+      </Created>
+      <Hr />
+      <Box sx={{ display: 'flex', justifyContent: 'space-between', margin: 1 }}>
+        <span>
+          <Bold>
+            {num}
+          </Bold>
+          <Light>Members</Light>
+        </span>
+        <span>
+          <SpecialBold>
+            1.0k
+          </SpecialBold>
+          <Light>Online</Light>
+        </span>
+        <span>
+          <Bold>Top 1%</Bold>
+          <Light>Ranked by Size</Light>
+        </span>
+        <div />
+      </Box>
+      { !createPost && (
+      <CustomLink to={`/submit/r/${Name}`}>
+        <CreatPost variant="outlined" padding="4px" fontSize={15} fontWeight="bold">
+          create Post
+        </CreatPost>
+      </CustomLink>
+      )}
+    </>
+  );
+}
+
+export default About;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_BackHome_BackHome.jsx.html b/docs/components_SubReddit_SideBar_BackHome_BackHome.jsx.html new file mode 100644 index 00000000..df656f6d --- /dev/null +++ b/docs/components_SubReddit_SideBar_BackHome_BackHome.jsx.html @@ -0,0 +1,80 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/BackHome/BackHome.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/BackHome/BackHome.jsx

+ + + + + + +
+
+
// eslint-disable-next-line import/no-named-as-default
+import BackHome from './style';
+/**
+ * function to handle in click back to to of page
+ * @component
+ * @returns top of the page
+ */
+function BackHomeBottun() {
+  function goToTop() {
+    document.documentElement.scrollTop = 0;
+    document.body.scrollTop = 0;
+  }
+  /**
+ * button on click on it back to top of bage
+ * @return {React.Component} - button
+ */
+  return (
+    <BackHome
+      variant="contained"
+      fontSize={15}
+      fontWeight="bold"
+      onClick={() => goToTop()}
+    >
+      Back to Top
+    </BackHome>
+  );
+}
+
+export default BackHomeBottun;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_Flirt_Flirt.jsx.html b/docs/components_SubReddit_SideBar_Flirt_Flirt.jsx.html new file mode 100644 index 00000000..a98fa211 --- /dev/null +++ b/docs/components_SubReddit_SideBar_Flirt_Flirt.jsx.html @@ -0,0 +1,112 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/Flirt/Flirt.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/Flirt/Flirt.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import { useEffect, useMemo, useState } from 'react';
+import { useParams } from 'react-router-dom';
+import useFetch from './flirtServer';
+import {
+  Button,
+  Container, See, Span, String,
+} from './style';
+/**
+ * Filter section
+ * @component
+ * @return {React.Component} - Filter section
+ */
+function Flirt() {
+  const [flair, setFalir] = useState([]);
+  const [show, setShow] = useState(false);
+  const { Name } = useParams();
+  const [data, dataError] = useFetch(Name);
+  console.log(data);
+
+  const value = useMemo(() => ({ data, dataError }), [data, dataError]);
+  console.log(value);
+  useEffect(() => {
+    setFalir(data);
+    console.log(dataError);
+  }, [flair, data]);
+
+  return (
+    <div>
+      { (flair?.length > 0)
+        && (
+        <>
+          <Container>
+            <String>
+              Filter by flair
+            </String>
+          </Container>
+          <Box sx={{ padding: '12px' }}>
+            { (flair.slice(0, 8))?.map((entity, index) => (
+              <Box sx={{ paddingBottom: 1, display: 'inline-block' }}>
+                <Button key={`${index + 0}`} backgroundColor={entity.backgroundColor}><Span color={entity.textColor}>{entity.text}</Span></Button>
+              </Box>
+            ))}
+            {show
+            && (flair.slice(8))?.map((entity, index) => (
+              <Box sx={{ paddingBottom: 1, display: 'inline-block' }}>
+                <Button key={`${index + 0}`} backgroundColor={entity.backgroundColor}><Span color={entity.textColor}>{entity.text}</Span></Button>
+              </Box>
+            ))}
+          </Box>
+          {show
+          && <See onClick={() => { setShow(false); }}> See Less </See>}
+          {!show
+          && <See onClick={() => { setShow(true); }}> See more </See>}
+        </>
+        )}
+    </div>
+  );
+}
+
+export default Flirt;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_Flirt_flirtServer.js.html b/docs/components_SubReddit_SideBar_Flirt_flirtServer.js.html new file mode 100644 index 00000000..42b56c72 --- /dev/null +++ b/docs/components_SubReddit_SideBar_Flirt_flirtServer.js.html @@ -0,0 +1,83 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/Flirt/flirtServer.js + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/Flirt/flirtServer.js

+ + + + + + +
+
+
import { useState, useEffect } from 'react';
+import axios from '../../../../services/instance';
+/**
+ * Get flairs for subreddit
+ *
+ * @property {string} Name - name of subreddit
+
+ */
+const useFetch = (Name) => {
+  const [data, setData] = useState(null);
+  const [error, setError] = useState(null);
+  const [statusCode, setStatusCode] = useState(null);
+
+  useEffect(() => {
+    axios.get(`/subreddits/${Name}/flair`).then((response) => {
+      // console.log(response);
+      setData(response.data);
+      setStatusCode(response.status);
+      // console.log(response.data);
+      setError(null);
+    }).catch((error) => {
+      setError(error);
+      setStatusCode(error.response.status);
+      console.log(error);
+    });
+  }, []);
+  if (statusCode === 401) {
+    window.location.pathname = 'login';
+  }
+  return [data?.data, error];
+};
+export default useFetch;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_Mderation_AddDisc_Add.jsx.html b/docs/components_SubReddit_SideBar_Mderation_AddDisc_Add.jsx.html new file mode 100644 index 00000000..398cfd39 --- /dev/null +++ b/docs/components_SubReddit_SideBar_Mderation_AddDisc_Add.jsx.html @@ -0,0 +1,220 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/Mderation/AddDisc/Add.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/Mderation/AddDisc/Add.jsx

+ + + + + + +
+
+
import { Box, ClickAwayListener } from '@mui/material';
+import { useState, useEffect } from 'react';
+import ModeEditOutlineOutlinedIcon from '@mui/icons-material/ModeEditOutlineOutlined';
+import EmptyStr from '../../../../../utils/EmptyStr';
+
+import patchData from '../ModerationServer';
+
+import {
+  AboutContent, Action, Add, Count, Input, InputFooter, Text,
+} from './style';
+import CustomizedDialogs from './DiscAlerdt/DistAlert';
+/**
+ * Add discreption for the community
+ * @component
+ * @property  {function} handleClickAway1 return to defult mode when click away
+ * @property  {function} handleChange count number of char in input feild to make sure not exeed the limit
+ * @property  {function} falseShow close the input
+ * @property  {function} sendData send data to backend
+ * @property  {function} SaveAction save all data and send to backend
+ * @property  {function} decord descord all changes in input
+
+ * @return {React.Component} - Add discreption for the community
+ */
+function AddSector(props) {
+  const { disc2, Name } = props;
+  const [show, setShow] = useState(true);
+  const [count, setCount] = useState(500);
+  const [tempString, setTempString] = useState('');
+  const [disc, setDisc] = useState(disc2);
+  const [haveDisc, setHaveDisc] = useState(true);
+  // return to defult mode when click away
+  const handleClickAway1 = () => {
+    const ele = document.getElementById('discInput');
+    if (disc !== ele?.value?.trim() && !show) {
+      const alert = document.getElementById('DiscAlert');
+      console.log(show);
+      alert.click();
+    } else {
+      setShow(true);
+    }
+  };
+  useEffect(() => {
+    setTempString(disc2?.trim());
+    setDisc(disc2?.trim());
+    const a = disc2?.trim()?.length;
+    setCount(500 - a);
+    if (disc2?.trim()?.length > 0) {
+      setHaveDisc(true);
+    } else {
+      setHaveDisc(false);
+    }
+  }, [disc2]);
+
+  // count number of char in input feild to make sure not exeed the limit
+  const handleChange = (event) => {
+    if (event.target.value.length < 501) {
+      setTempString(event?.target?.value);
+      setCount(500 - event.target.value.length);
+    }
+  };
+  const falseShow = () => {
+    setShow(false);
+  };
+  const sendData = () => {
+    console.log(Name);
+
+    patchData(Name, { description: tempString?.trim() }); // fetch api
+  };
+  const SaveAction = async () => {
+    setShow(true);
+    setDisc(tempString.trim());
+    setTempString(tempString.trim());
+    await setCount(500 - tempString.trim().toString().length);
+    if (EmptyStr(tempString.trim()?.trim())) { setHaveDisc(false); } else {
+      setHaveDisc(true);
+    }
+    sendData();
+    // sendData();
+  };
+  const decord = () => {
+    setShow(true);
+    setTempString(disc);
+    setDisc(disc);
+    setCount(500 - disc.length);
+    if (!EmptyStr(disc)) {
+      setHaveDisc(true);
+    }
+  };
+  const c = disc?.length;
+
+  useEffect(() => {
+    console.log(show, disc2?.trim()?.length, haveDisc);
+  }, [show, disc2, haveDisc]);
+
+  return (
+    <AboutContent>
+
+      <ClickAwayListener onClickAway={handleClickAway1}>
+        <Add>
+          <CustomizedDialogs falseShow={falseShow} SaveAction={SaveAction} decord={decord} />
+          <Box data-testid="add" onClick={() => { setShow(false); setCount(500 - c); }} sx={{ display: 'flex', overflowWrap: 'anywhere' }}>
+            {show && !haveDisc && <Text> Add description</Text>}
+            {(haveDisc && show) && (
+              <>
+                <Text>
+                  {' '}
+                  {disc}
+                </Text>
+                {' '}
+                <ModeEditOutlineOutlinedIcon color="primary" />
+              </>
+            )}
+          </Box>
+          {!show
+            && (
+              <>
+                <Input
+                  data-testid="input"
+                  type="text"
+                  id="discInput"
+                  value={tempString}
+                  placeholder="Tell us About your community"
+                  onChange={handleChange}
+                  onInput={(e) => {
+                  // eslint-disable-next-line radix
+                    e.target.value = e.target.value.slice(0, 500);
+                    setTempString(e.target.value = e.target.value.slice(0, 500));
+                    e.target.style.height = `${e.target.scrollHeight}px`;
+                  }}
+                />
+                <InputFooter>
+                  <Count
+                    condition={(count === 0).toString()}
+                  >
+                    {count}
+                    {' '}
+                    Characters remaining
+                  </Count>
+                  <Box sx={{ display: 'flex' }}>
+                    <Action
+                      onClick={() => {
+                        setShow(true); setDisc(''); setTempString(''); setCount(500 - disc.length);
+                        setHaveDisc(false); sendData();
+                      }}
+                      sx={{ marginRight: '8px' }}
+                      color="red"
+                      data-testid="cancel"
+                    >
+                      Cancel
+                    </Action>
+                    <Action
+                      onClick={SaveAction}
+                      color="#0079d3"
+                      id="save"
+
+                    >
+                      Save
+
+                    </Action>
+                  </Box>
+                </InputFooter>
+              </>
+            )}
+        </Add>
+      </ClickAwayListener>
+    </AboutContent>
+  );
+}
+export default AddSector;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_Mderation_AddDisc_DiscAlerdt_DistAlert.jsx.html b/docs/components_SubReddit_SideBar_Mderation_AddDisc_DiscAlerdt_DistAlert.jsx.html new file mode 100644 index 00000000..7c7df94e --- /dev/null +++ b/docs/components_SubReddit_SideBar_Mderation_AddDisc_DiscAlerdt_DistAlert.jsx.html @@ -0,0 +1,155 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/Mderation/AddDisc/DiscAlerdt/DistAlert.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/Mderation/AddDisc/DiscAlerdt/DistAlert.jsx

+ + + + + + +
+
+
import * as React from 'react';
+import PropTypes from 'prop-types';
+import Button from '@mui/material/Button';
+import { styled } from '@mui/material/styles';
+import Dialog from '@mui/material/Dialog';
+import DialogTitle from '@mui/material/DialogTitle';
+import DialogContent from '@mui/material/DialogContent';
+import DialogActions from '@mui/material/DialogActions';
+import IconButton from '@mui/material/IconButton';
+import CloseIcon from '@mui/icons-material/Close';
+import Typography from '@mui/material/Typography';
+import { Join, JoinCommunity } from './style';
+
+/**
+ * Alert when left description input and change it
+ * @component
+ *
+ * @return {React.Component} - Alert when left description input and change it
+ */
+
+const BootstrapDialog = styled(Dialog)(({ theme }) => ({
+  '& .MuiDialogContent-root': {
+    padding: theme.spacing(2),
+  },
+  '& .MuiDialogActions-root': {
+    padding: theme.spacing(1),
+  },
+}));
+
+function BootstrapDialogTitle(props) {
+  const {
+    falseShow, children, onClose, ...other
+  } = props;
+
+  return (
+    <DialogTitle sx={{ m: 0, p: 2 }} {...other} onClick={onClose}>
+      {children}
+      {onClose ? (
+        <IconButton
+          aria-label="close"
+          onClick={() => { falseShow(); onClose(); }}
+          sx={{
+            position: 'absolute',
+            right: 8,
+            top: 8,
+            color: (theme) => theme.palette.grey[500],
+          }}
+        >
+          <CloseIcon onClick={() => { falseShow(); onClose(); }} />
+        </IconButton>
+      ) : null}
+    </DialogTitle>
+  );
+}
+
+BootstrapDialogTitle.propTypes = {
+  // eslint-disable-next-line react/require-default-props
+  children: PropTypes.node,
+  onClose: PropTypes.func.isRequired,
+};
+
+export default function CustomizedDialogs(props) {
+  const [openForm, setopenForm] = React.useState(false);
+  const { falseShow, SaveAction, decord } = props;
+  const handleClickOpen = () => {
+    setopenForm(true);
+  };
+  const handleClose = () => {
+    setopenForm(false);
+  };
+
+  return (
+    <div>
+      <Button variant="outlined" onClick={handleClickOpen} id="DiscAlert" sx={{ display: 'none' }}>
+        openForm dialog
+      </Button>
+      {openForm && (
+      <BootstrapDialog
+        onClose={handleClose}
+        aria-labelledby="customized-dialog-title"
+        open={openForm}
+        falseShow={falseShow}
+      >
+        <BootstrapDialogTitle id="customized-dialog-title" onClose={handleClose}>
+          Save changes before leaving?
+        </BootstrapDialogTitle>
+        <DialogContent dividers>
+          <Typography gutterBottom>
+            You have made some changes to your community, do you wish to leave this menu without saving?
+          </Typography>
+        </DialogContent>
+        <DialogActions>
+          <Join autoFocus onClick={() => { decord(); handleClose(); }}>
+            Discard
+          </Join>
+          <JoinCommunity autoFocus onClick={() => { handleClose(); SaveAction(); }}>
+            Save
+          </JoinCommunity>
+        </DialogActions>
+      </BootstrapDialog>
+      )}
+    </div>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_Mderation_AddList_Add Bottun_AddBtn.jsx.html b/docs/components_SubReddit_SideBar_Mderation_AddList_Add Bottun_AddBtn.jsx.html new file mode 100644 index 00000000..9a240967 --- /dev/null +++ b/docs/components_SubReddit_SideBar_Mderation_AddList_Add Bottun_AddBtn.jsx.html @@ -0,0 +1,188 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/Mderation/AddList/Add Bottun/AddBtn.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/Mderation/AddList/Add Bottun/AddBtn.jsx

+ + + + + + +
+
+
import ClearOutlinedIcon from '@mui/icons-material/ClearOutlined';
+import ModeEditOutlineOutlinedIcon from '@mui/icons-material/ModeEditOutlineOutlined';
+import AddOutlinedIcon from '@mui/icons-material/AddOutlined';
+import {
+  Action,
+  Add, BOX, Count, Input, InputFooter, Text,
+} from './style';
+import CustomizedDialogs from './ListAlert/Alert';
+
+const { ClickAwayListener, Box } = require('@mui/material');
+
+/**
+ * Add item to list of topics
+ * @component
+ * @property  {function} SaveAction save new data and send to backend
+ *
+ * @return {React.Component} -  Add item to list of topics
+ */
+function AddBtn(props) {
+  const { sendData } = props;
+  const {
+    handleClickAway1, falseShaw, show, tempString, removeItem, tags, handleChange, handleKeyDown, trueShawList, trueShaw,
+    setTemp, setTag, count, decord,
+  } = props;
+  const SaveAction = () => {
+    setTag(tempString);
+    setTemp(tempString);
+    sendData();
+    // console.log(tempString);
+    // sendData();
+    trueShaw();
+  };
+
+  return (
+    <ClickAwayListener onClickAway={handleClickAway1}>
+
+      <Add data-testid="add" condition={show?.toString()} onClick={() => { falseShaw(); }} id="add">
+        <CustomizedDialogs falseShow={falseShaw} SaveAction={SaveAction} decord={decord} />
+        <>
+          <Box sx={{ display: 'flex', flexDirection: 'row', flexWrap: 'wrap' }}>
+            {tempString?.length === 0
+              && show && (
+              <Text condition={show?.toString()} sx={{ alignItems: 'center' }}>
+                <AddOutlinedIcon color="primary" />
+                Add Subject
+              </Text>
+            )}
+            {tempString?.length > 0 && (tempString.slice(0, 4))?.map((tag, index) => (
+              <Text key={`${index + 0}`} condition={show?.toString()}>
+                {tag}
+                <ClearOutlinedIcon
+                  fontSize="small"
+                  onClick={() => {
+                    removeItem(index);
+                  }}
+                />
+              </Text>
+            )) }
+            { !show && tags?.length > 0
+              && (tempString.slice(4))?.map((temp, index) => (
+                <Text key={`${index + 0}`} condition={show?.toString()}>
+                  {temp}
+                  <ClearOutlinedIcon
+                    fontSize="small"
+                    onClick={() => {
+                      removeItem(index + 4);
+                    }}
+                    sx={{ color: 'gray' }}
+                  />
+                </Text>
+              )) }
+            {show && tempString?.length > 4 && (
+              <BOX>
+                +
+                {tempString.length - 4}
+              </BOX>
+            )}
+            {show && tempString?.length > 0 && <ModeEditOutlineOutlinedIcon />}
+          </Box>
+          {!show
+            && (
+            <Input
+              data-testid="input"
+              autoFocus
+              id="input"
+              type="text"
+              onChange={handleChange}
+              onFocus={trueShawList}
+              onInput={(e) => {
+                // eslint-disable-next-line radix
+                e.target.style.height = `${e.target.scrollHeight}px`;
+              }}
+              onKeyDown={handleKeyDown}
+            />
+            )}
+        </>
+        {!show && (
+          <InputFooter>
+            <Count
+              condition={(count === 25).toString()}
+            >
+              {tempString?.length}
+              /
+              25
+            </Count>
+            <Box sx={{ display: 'flex', marginTop: '1px' }}>
+              <Action
+                onClick={(e) => {
+                  e.stopPropagation();
+                  trueShaw();
+                  setTemp(tags);
+                  setTemp(tags);
+                  sendData();
+                }}
+                id="cancel"
+                color="red"
+                sx={{ marginRight: '8px' }}
+              >
+                Cancel
+              </Action>
+              <Action
+                color="#0079d3"
+                onClick={(e) => {
+                  e.stopPropagation();
+                  SaveAction();
+                }}
+              >
+                Save
+              </Action>
+            </Box>
+          </InputFooter>
+        )}
+      </Add>
+    </ClickAwayListener>
+  );
+}
+export default AddBtn;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_Mderation_AddList_Add Bottun_ListAlert_Alert.jsx.html b/docs/components_SubReddit_SideBar_Mderation_AddList_Add Bottun_ListAlert_Alert.jsx.html new file mode 100644 index 00000000..5ac98a39 --- /dev/null +++ b/docs/components_SubReddit_SideBar_Mderation_AddList_Add Bottun_ListAlert_Alert.jsx.html @@ -0,0 +1,155 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/Mderation/AddList/Add Bottun/ListAlert/Alert.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/Mderation/AddList/Add Bottun/ListAlert/Alert.jsx

+ + + + + + +
+
+
import * as React from 'react';
+import PropTypes from 'prop-types';
+import Button from '@mui/material/Button';
+import { styled } from '@mui/material/styles';
+import Dialog from '@mui/material/Dialog';
+import DialogTitle from '@mui/material/DialogTitle';
+import DialogContent from '@mui/material/DialogContent';
+import DialogActions from '@mui/material/DialogActions';
+import IconButton from '@mui/material/IconButton';
+import CloseIcon from '@mui/icons-material/Close';
+import Typography from '@mui/material/Typography';
+import { Join, JoinCommunity } from './style';
+
+/**
+ * Alert when left list of topics input and change it
+ * @component
+ *
+ * @return {React.Component} - Alert when left list of topics input and change it
+ */
+
+const BootstrapDialog = styled(Dialog)(({ theme }) => ({
+  '& .MuiDialogContent-root': {
+    padding: theme.spacing(2),
+  },
+  '& .MuiDialogActions-root': {
+    padding: theme.spacing(1),
+  },
+}));
+
+function BootstrapDialogTitle(props) {
+  const {
+    falseShow, children, onClose, ...other
+  } = props;
+
+  return (
+    <DialogTitle sx={{ m: 0, p: 2 }} {...other} onClick={onClose}>
+      {children}
+      {onClose ? (
+        <IconButton
+          aria-label="close"
+          onClick={() => { falseShow(); onClose(); }}
+          sx={{
+            position: 'absolute',
+            right: 8,
+            top: 8,
+            color: (theme) => theme.palette.grey[500],
+          }}
+        >
+          <CloseIcon onClick={() => { falseShow(); onClose(); }} />
+        </IconButton>
+      ) : null}
+    </DialogTitle>
+  );
+}
+
+BootstrapDialogTitle.propTypes = {
+  // eslint-disable-next-line react/require-default-props
+  children: PropTypes.node,
+  onClose: PropTypes.func.isRequired,
+};
+
+export default function CustomizedDialogs(props) {
+  const [openForm, setopenForm] = React.useState(false);
+  const { falseShow, SaveAction, decord } = props;
+  const handleClickOpen = () => {
+    setopenForm(true);
+  };
+  const handleClose = () => {
+    setopenForm(false);
+  };
+
+  return (
+    <div>
+      <Button variant="outlined" onClick={handleClickOpen} id="ListAlert" sx={{ display: 'none' }}>
+        openForm dialog
+      </Button>
+      {openForm && (
+      <BootstrapDialog
+        onClose={handleClose}
+        aria-labelledby="customized-dialog-title"
+        open={openForm}
+        falseShow={falseShow}
+      >
+        <BootstrapDialogTitle id="customized-dialog-title" onClose={handleClose}>
+          Save changes before leaving?
+        </BootstrapDialogTitle>
+        <DialogContent dividers>
+          <Typography gutterBottom>
+            You have made some changes to your community, do you wish to leave this menu without saving?
+          </Typography>
+        </DialogContent>
+        <DialogActions>
+          <Join autoFocus onClick={(e) => { e.stopPropagation(); handleClose(); decord(); }}>
+            Discard
+          </Join>
+          <JoinCommunity autoFocus onClick={(e) => { e.stopPropagation(); handleClose(); SaveAction(); }}>
+            Save
+          </JoinCommunity>
+        </DialogActions>
+      </BootstrapDialog>
+      )}
+    </div>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_Mderation_AddList_AddList.jsx.html b/docs/components_SubReddit_SideBar_Mderation_AddList_AddList.jsx.html new file mode 100644 index 00000000..291aa5e9 --- /dev/null +++ b/docs/components_SubReddit_SideBar_Mderation_AddList_AddList.jsx.html @@ -0,0 +1,217 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/Mderation/AddList/AddList.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/Mderation/AddList/AddList.jsx

+ + + + + + +
+
+
import {
+  //  Box, ClickAwayListener,
+  ListItem, ListItemText,
+} from '@mui/material';
+import { useState, useEffect } from 'react';
+import KeyDown from '../../../../../utils/KeyDown';
+import FilterArray from '../../../../../utils/FilterArray';
+
+import patchData from '../ModerationServer';
+
+import AddBtn from './Add Bottun/AddBtn';
+import {
+  AboutContent, Lists,
+} from './style';
+
+const primary = ['Activism', 'Art', 'Addiction Support', 'Anime', 'Beauty and Makeup', 'Business, Economics, and Finance', 'Careers', 'Cars and Motor Vehicles',
+  'Celebrity', 'Crafts and DIY', 'Crypto', 'Culture, Race, and Ethnicity', 'Ethics and Philosophy', 'Family and Relationships', 'Fashion', 'Fitness and Nutrition',
+  'Food and Drink', 'Funny/Humor', 'Gamming', 'Gender', 'History', 'Hobbies', 'Home and Garden', 'Home and Garden', 'Learning and Education', 'Law', 'Marketplace and Deals',
+  'Mature Themes and Adult Content', 'Medical and Mental Health', "Men's Health", 'Meta/Reddit', 'Outdoors and Nature', 'Militery', 'Moves', 'Music', 'Outdoors and Nature', 'Place',
+  'Podcasts and Streamers', 'Polices', 'Progeamming', 'Reading, Writing, and Literature'];
+/**
+ * AddList(community topics)
+ * @component
+ * @property  {function} handleKeyDown  handel on press enter to add the community topic
+ * @property  {function} removeItem to rempve element when press x
+ * @property  {function} ListSelected add item when select from list
+ * @property  {function} trueShaw open the input
+ * @property  {function} falseShaw clase the input
+ * @property  {function} trueShawList open the list ip topics
+ * @property  {function} setTemp set new list of topics
+ * @property  {function} setTag set new list of topics
+ * @property  {function} sendData send data to backend
+ * @property  {function} handleClickAway1 return to default view of add list
+ * @property  {function} decord descord all changes
+
+ * @return {React.Component} - AddList(community topics)
+ */
+function AddList(props) {
+  const {
+    topics, Name,
+  } = props;
+  const [show, setShow] = useState(true);
+  const [showList, setShowList] = useState(true);
+  // eslint-disable-next-line prefer-const
+  const [tags, setTags] = useState(topics);
+  const [tempString, setTempString] = useState(tags);
+  const [count, setCount] = useState(tags?.length);
+
+  useEffect(() => {
+    setTags(topics);
+    setTempString(topics);
+  }, [topics]);
+  // save the change in input field to get count if char
+  const handleChange = (event) => {
+    console.log((event.target > 'Text').length);
+    if (event.target.value.length < 26) {
+      setCount((event.target > 'Text').length);
+    }
+  };
+  // handel on press enter to add the community topic
+  const handleKeyDown = (e) => {
+    if (KeyDown(tempString, e.target.value)) {
+      if (e.key !== 'Enter') return;
+      const { value } = e.target;
+      if (!value.trim()) return;
+      setTempString([...tempString, value]);
+    }
+    e.target.value = '';
+  };
+  // to rempve element when press x
+  const removeItem = (value) => {
+    setTempString(FilterArray(tempString, value));
+  };
+
+  // add item when select from list
+  const ListSelected = (e) => {
+    e.stopPropagation();
+    if (!tempString.includes(e.target.textContent)) {
+      setTempString([...tempString, e.target.textContent]);
+      const btn = document.getElementById('add');
+      btn.click();
+      const input = document.getElementById('input');
+      input.focus();
+    }
+  };
+  const trueShaw = () => {
+    setShow(true);
+  };
+  const falseShaw = () => {
+    setShow(false);
+  };
+  const trueShawList = () => {
+    setShowList(true);
+  };
+  const setTemp = (t) => {
+    setTempString(t);
+  };
+  const setTag = (t) => {
+    setTags(t);
+  };
+  const sendData = () => {
+    patchData(Name, { topics: tempString }); // fetch api
+  };
+    // return to default view of add list
+  const handleClickAway1 = () => {
+    // setTags(tempString);
+    setShow(true);
+    // setCount(tags.length);
+    // sendData();
+
+    console.log('hello');
+    if (tags !== tempString && !show) {
+      const alert = document.getElementById('ListAlert');
+      console.log('show');
+      alert.click();
+    } else {
+      // setShow(true);
+    }
+  };
+  const decord = () => {
+    trueShaw();
+    setTempString(tags);
+    setTag(tags);
+    setCount(500 - tags.length);
+    setShow(true);
+    trueShaw();
+    console.log(show);
+  };
+  return (
+    <AboutContent>
+      <AddBtn sendData={sendData} decord={decord} handleClickAway1={handleClickAway1} setTag={setTag} setTemp={setTemp} trueShaw={trueShaw} trueShawList={trueShawList} handleChange={handleChange} handleKeyDown={handleKeyDown} removeItem={removeItem} falseShaw={falseShaw} show={show} tempString={tempString} tags={tags} count={count} />
+      {
+          tempString?.length < 25 && showList
+          && !show
+          && (
+            <Lists
+              subheader={<li />}
+            >
+              {[0].map((sectionId) => (
+                <li key={`section-${sectionId}`}>
+                  <ul>
+                    {primary.map((item) => (
+                      <ListItem key={`item-${sectionId}-${item}`}>
+                        <ListItemText
+                          primary={`${item}`}
+                          sx={{
+                            span: {
+                              fontWeight: 700,
+                              fontSize: 13,
+                              cursor: 'pointer',
+                            },
+                          }}
+                          onClick={ListSelected}
+                        />
+                      </ListItem>
+                    ))}
+                  </ul>
+                </li>
+              ))}
+            </Lists>
+          )
+        }
+    </AboutContent>
+  );
+}
+export default AddList;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_Mderation_Moderation.jsx.html b/docs/components_SubReddit_SideBar_Mderation_Moderation.jsx.html new file mode 100644 index 00000000..886ad279 --- /dev/null +++ b/docs/components_SubReddit_SideBar_Mderation_Moderation.jsx.html @@ -0,0 +1,237 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/Mderation/Moderation.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/Mderation/Moderation.jsx

+ + + + + + +
+
+
import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined';
+import {
+  Box, IconButton, ListItem, ListItemText, ClickAwayListener,
+} from '@mui/material';
+import AdminPanelSettingsOutlinedIcon from '@mui/icons-material/AdminPanelSettingsOutlined';
+import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
+import { useEffect, useState } from 'react';
+import ExpandMoreOutlinedIcon from '@mui/icons-material/ExpandMoreOutlined';
+import ExpandLessOutlinedIcon from '@mui/icons-material/ExpandLessOutlined';
+import moment from 'moment/moment';
+import patchData from './ModerationServer';
+import Sort from '../MoreIcon/More';
+import {
+  AboutCountainer, AboutString, CreatedSpan,
+  More, Created, Icon, Hr, Bold, Light, SpecialBold, CustomLink,
+  CreatPost, Admin, New,
+  Select, Lists, SelectContainer, StyledTooltip,
+} from './style';
+import AddSector from './AddDisc/Add';
+import AddList from './AddList/AddList';
+/**
+ * About section in sidebar for moderators only instead of about section for normal users
+ * @component
+ * @property  {function} changeShow show select list or not
+ * @property  {function} sendData send data to backend
+ * @property  {function} ListSelected handel on select item
+ * @property  {function} handleClickAway close the list in  click away
+ *
+ * @return {React.Component} - About section in sidebar for moderators only instead of about section for normal users
+ */
+function Moderation(props) {
+  const {
+    topics, disc, Name, primaryTopic, createdAt, num,
+  } = props;
+  const [more, setMore] = useState(false);
+  const [listOfTopics, setListOfTopics] = useState(false);
+  const [selection, setSelection] = useState(primaryTopic);
+
+  const primary = ['Activism', 'Art', 'Addiction Support', 'Anime', 'Beauty and Makeup', 'Business, Economics, and Finance', 'Careers', 'Cars and Motor Vehicles',
+    'Celebrity', 'Crafts and DIY', 'Crypto', 'Culture, Race, and Ethnicity', 'Ethics and Philosophy', 'Family and Relationships', 'Fashion', 'Fitness and Nutrition',
+    'Food and Drink', 'Funny/Humor', 'Gamming', 'Gender', 'History', 'Hobbies', 'Home and Garden', 'Home and Garden', 'Learning and Education', 'Law', 'Marketplace and Deals',
+    'Mature Themes and Adult Content', 'Medical and Mental Health', "Men's Health", 'Meta/Reddit', 'Outdoors and Nature', 'Militery', 'Moves', 'Music', 'Outdoors and Nature', 'Place',
+    'Podcasts and Streamers', 'Polices', 'Progeamming', 'Reading, Writing, and Literature'];
+
+  useEffect(() => {
+    setSelection(primaryTopic);
+    if (primaryTopic === 'Add a Primary Topic' || selection === 'Add a Primary Topic') {
+      setListOfTopics(false);
+    } else {
+      setListOfTopics(true);
+    }
+  }, [primaryTopic]);
+  // show select list or not
+  const changeShow = () => {
+    setMore(!more);
+    // setSelection('Add a Primary Topic');
+  };
+
+  const sendData = (val) => {
+    patchData(Name, { primaryTopic: val }); // fetch api
+  };
+
+  // handel on select item
+  const ListSelected = (e) => {
+    setMore(!more);
+    setSelection(e.target.textContent);
+    setListOfTopics(true);
+    sendData(e.target.textContent);
+  };
+
+  // close the list in  click away
+  const handleClickAway = () => {
+    setMore(false);
+  };
+  return (
+    <>
+      <AboutCountainer>
+        <AboutString>
+          About Community
+        </AboutString>
+        <More>
+          <Admin to={`/r/${Name}/about`}>
+            <AdminPanelSettingsOutlinedIcon />
+            Mood Tools
+          </Admin>
+          <Sort margin={15} />
+        </More>
+      </AboutCountainer>
+      <AddSector disc2={disc} Name={Name} />
+
+      <Created>
+        <Icon><EmailOutlinedIcon /></Icon>
+        <CreatedSpan>
+          Created
+          {' '}
+          {moment(createdAt).add(1, 'days').utc().format('MMMMย DD,ย YYYY')}
+        </CreatedSpan>
+      </Created>
+      <Hr />
+      <Box sx={{
+        display: 'flex', justifyContent: 'space-between', paddingLeft: 3,
+      }}
+      >
+        <span>
+          <Bold>
+            {num}
+          </Bold>
+          <Light>Members</Light>
+        </span>
+        <span>
+          <SpecialBold>
+            1.0k
+          </SpecialBold>
+          <Light>Online</Light>
+        </span>
+        <span />
+        <div />
+      </Box>
+      <Hr sx={{ marginTop: 0 }} />
+      <Box sx={{ display: 'flex', alignItems: 'center', marginLeft: '4px' }}>
+        {!listOfTopics && <New>New</New>}
+        Community topics
+        <StyledTooltip title="Adding community topics allow people to find your community. Add a primary topic and sub topics to be discovered more easily.">
+          <IconButton>
+            <ErrorOutlineIcon sx={{
+              transform: 'rotate(180deg)',
+              color: 'gray',
+              '&:hover': {
+                color: '#288eda',
+              },
+            }}
+            />
+          </IconButton>
+        </StyledTooltip>
+      </Box>
+
+      <SelectContainer
+        onClick={changeShow}
+      >
+        <Select data-testid="select">{selection}</Select>
+        {!more && <ExpandMoreOutlinedIcon color="primary" sx={{ marginTop: '7px', marginLeft: '5px' }} />}
+        {more && <ExpandLessOutlinedIcon color="primary" sx={{ marginTop: '7px', marginLeft: '5px' }} />}
+      </SelectContainer>
+
+      {more
+      && (
+        <ClickAwayListener onClickAway={handleClickAway}>
+          <Lists
+            data-testid="list"
+            subheader={<li />}
+          >
+            {[0].map((sectionId) => (
+              <li key={`section-${sectionId}`}>
+                <ul>
+                  {primary.map((item) => (
+                    <ListItem key={`item-${sectionId}-${item}`}>
+                      <ListItemText
+                        primary={`${item}`}
+                        sx={{
+                          span: {
+                            fontWeight: 700,
+                            fontSize: 13,
+                            cursor: 'pointer',
+                          },
+                        }}
+                        onClick={ListSelected}
+                      />
+                    </ListItem>
+                  ))}
+                </ul>
+              </li>
+            ))}
+          </Lists>
+        </ClickAwayListener>
+      )}
+      {listOfTopics && <AddList topics={topics} Name={Name} listOfTopics={listOfTopics} />}
+      <Hr sx={{ marginBottom: 1, marginTop: 0 }} />
+      <CustomLink to={`/submit/r/${Name}`}>
+        <CreatPost variant="outlined" padding="4px" fontSize={15} fontWeight="bold">
+          create Post
+        </CreatPost>
+      </CustomLink>
+    </>
+  );
+}
+export default Moderation;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_Mderation_ModerationServer.js.html b/docs/components_SubReddit_SideBar_Mderation_ModerationServer.js.html new file mode 100644 index 00000000..cca0fbe3 --- /dev/null +++ b/docs/components_SubReddit_SideBar_Mderation_ModerationServer.js.html @@ -0,0 +1,76 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/Mderation/ModerationServer.js + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/Mderation/ModerationServer.js

+ + + + + + +
+
+
import Done from '../../../AlertMessage';
+import axios from '../../../../services/instance';
+/**
+ * edit data for moderation
+ *
+ * @property {string} Name - name of subreddit
+ * @property {object} prefs - data to change
+
+ */
+const patchData = async (Name, prefs) => {
+  let statusCode = '';
+  await axios.patch(`subreddits/${Name}`, prefs).then((response) => {
+    statusCode = response.status;
+  }).catch((error) => {
+    statusCode = error.response.status;
+    console.log(error);
+  });
+  if (statusCode === 200 || statusCode === 200) {
+    Done('Chanes Save');
+  }
+  if (statusCode === 401) {
+    window.location.pathname = 'login';
+  }
+};
+export default patchData;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_Moderators_Moderators.jsx.html b/docs/components_SubReddit_SideBar_Moderators_Moderators.jsx.html new file mode 100644 index 00000000..d082facb --- /dev/null +++ b/docs/components_SubReddit_SideBar_Moderators_Moderators.jsx.html @@ -0,0 +1,91 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/Moderators/Moderators.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/Moderators/Moderators.jsx

+ + + + + + +
+
+
import MailOutlineIcon from '@mui/icons-material/MailOutline'; import {
+  AboutCountainer, AboutString, CustomLink, Button, Container, Name, ViewAll, ViewAllContainer,
+} from './style';
+/**
+ * Moderators section in sidebar
+ * @component
+ * @return {React.Component} - Moderators section in sidebar
+ */
+function Moderators(props) {
+  const { moderatoesName } = props;
+  return (
+    <>
+      <AboutCountainer>
+        <AboutString>
+          Moderators
+        </AboutString>
+      </AboutCountainer>
+      <CustomLink>
+        <Button variant="outlined" padding="4px" fontSize={15} fontWeight="bold" sx={{ m: 1.8 }}>
+          <MailOutlineIcon sx={{ margin: '2px' }} />
+          {' '}
+          Message the Mods
+        </Button>
+      </CustomLink>
+      { moderatoesName?.map((entity, index) => (
+        <Container key={`${index + 0}`}>
+          <Name to={`/user/${entity}`}>
+            u/
+            {entity}
+          </Name>
+        </Container>
+      ))}
+      <ViewAllContainer>
+        <ViewAll>VIEW ALL MODERATORS</ViewAll>
+      </ViewAllContainer>
+    </>
+  );
+}
+
+export default Moderators;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_MoreIcon_More.jsx.html b/docs/components_SubReddit_SideBar_MoreIcon_More.jsx.html new file mode 100644 index 00000000..560b4dd1 --- /dev/null +++ b/docs/components_SubReddit_SideBar_MoreIcon_More.jsx.html @@ -0,0 +1,110 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/MoreIcon/More.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/MoreIcon/More.jsx

+ + + + + + +
+
+
import { Box } from '@mui/material';
+import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
+import { useState } from 'react';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+import {
+  Select, SelectBox, SelectItem,
+} from './style';
+/**
+ * More icon
+ * @component
+ * @property  {function} handleClick1 toggle showList or not
+ * @property  {function} handleClickAway1 handle disable the list when click away
+ * @property  {function} changeFavourit toggle favourit community
+
+ * @return {React.Component} - More icon
+ */
+export default function Sort(props) {
+  const { margin } = props;
+  const { marginLeft } = props;
+  const [showList1, setShowList1] = useState(false);
+  const [favourit, setFavourit] = useState('Add to Favorites');
+
+  // toggle the list when click
+  const handleClick1 = () => {
+    setShowList1((prev) => !prev);
+  };
+
+  // handle disable the list when click away
+  const handleClickAway1 = () => {
+    setShowList1(false);
+  };
+  const changeFavourit = () => {
+    if (favourit === 'Add to Favorites') {
+      setFavourit('Remove From Favorites');
+    } else {
+      setFavourit('Add to Favorites');
+    }
+  };
+  return (
+    <>
+      <Select>
+        <ClickAwayListener onClickAway={handleClickAway1}>
+          <Box data-testid="sort" sx={{ display: 'flex' }} onClick={() => { handleClick1(); }}>
+            <MoreHorizIcon />
+          </Box>
+        </ClickAwayListener>
+      </Select>
+      {showList1 && (
+      <SelectBox data-testid="items" sx={{ marginTop: margin, marginLeft }}>
+        <SelectItem>Add to Custom Feed</SelectItem>
+        <SelectItem onClick={changeFavourit}>
+          {favourit}
+        </SelectItem>
+      </SelectBox>
+      )}
+    </>
+
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_Rules_Entity_Entity.jsx.html b/docs/components_SubReddit_SideBar_Rules_Entity_Entity.jsx.html new file mode 100644 index 00000000..684a00a7 --- /dev/null +++ b/docs/components_SubReddit_SideBar_Rules_Entity_Entity.jsx.html @@ -0,0 +1,98 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/Rules/Entity/Entity.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/Rules/Entity/Entity.jsx

+ + + + + + +
+
+
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
+import { useState } from 'react';
+import {
+  AboutContent, AboutCountainerRule, AboutDisc, AboutStringRule, Hr,
+} from './style';
+
+/**
+ * Rule Entity
+ * @component
+ * @property  {function} handleClick toggle show rule or not
+
+ * @return {React.Component} - Rule Entity
+ */
+function Entity(props) {
+  const { rule, index } = props;
+  const [show, setShow] = useState(false);
+
+  const handleClick = () => {
+    setShow(!show);
+  };
+  return (
+    <>
+      <AboutCountainerRule key={`${index + 0}`}>
+        <AboutStringRule onClick={() => handleClick()}>
+          {index + 1}
+          .
+          {rule.title}
+          {show
+            ? <ExpandLessIcon />
+            : <ExpandMoreIcon />}
+        </AboutStringRule>
+      </AboutCountainerRule>
+      {show
+          && (
+          <AboutContent>
+            <AboutDisc>
+              {rule.description}
+            </AboutDisc>
+          </AboutContent>
+          )}
+      <Hr />
+    </>
+  );
+}
+
+export default Entity;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_Rules_Rules.jsx.html b/docs/components_SubReddit_SideBar_Rules_Rules.jsx.html new file mode 100644 index 00000000..4adc8366 --- /dev/null +++ b/docs/components_SubReddit_SideBar_Rules_Rules.jsx.html @@ -0,0 +1,82 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/Rules/Rules.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/Rules/Rules.jsx

+ + + + + + +
+
+
import {
+  AboutCountainer, AboutString,
+} from './style';
+import Entity from './Entity/Entity';
+
+/**
+ * About Rule
+ * @component
+ * @return {React.Component} - Add Rule
+ */
+function Rules(props) {
+  const { Name, rules } = props;
+
+  return (
+    <AboutCountainer>
+
+      <AboutString>
+        r/
+        {Name}
+      </AboutString>
+
+      { rules?.map((entity, index) => (
+        <Entity rule={entity} index={index} />
+      ))}
+
+    </AboutCountainer>
+
+  );
+}
+
+export default Rules;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SideBar_SideBar.jsx.html b/docs/components_SubReddit_SideBar_SideBar.jsx.html new file mode 100644 index 00000000..13217f02 --- /dev/null +++ b/docs/components_SubReddit_SideBar_SideBar.jsx.html @@ -0,0 +1,116 @@ + + + + + JSDoc: Source: components/SubReddit/SideBar/SideBar.jsx + + + + + + + + + + +
+ +

Source: components/SubReddit/SideBar/SideBar.jsx

+ + + + + + +
+
+
import { useState, useEffect } from 'react';
+import { SideBarContainer, CommunityContainer } from './style';
+import BackHome from './BackHome/BackHome';
+import About from './AboutSubReddit/About';
+import Moderators from './Moderators/Moderators';
+import Flirt from './Flirt/Flirt';
+import Moderation from './Mderation/Moderation';
+import numFormatter from '../../../utils/MembersNum';
+import UserLogin from '../../../authentication';
+import Rules from './Rules/Rules';
+/**
+ * SideBar for subreddit
+ * @component
+ * @return {React.Component} - SideBar for subreddit
+ */
+function SideBar(props) {
+  const {
+    disc, topics, Name, primaryTopic, createdAt, moderatoesName, username, members, rules, createPost,
+  } = props;
+  console.log('create post flag', createPost);
+  const [moderate, setModerate] = useState(false);
+  const finalArray = moderatoesName?.map((obj) => obj.user.userName);
+  // const finalArray = moderatoesName?.map((obj) => obj.userName);
+
+  const num = numFormatter(members);
+  const mode = UserLogin(finalArray);
+  console.log(mode);
+  useEffect(() => {
+    if (mode) {
+      setModerate(true);
+    } else {
+      setModerate(false);
+    }
+  }, [moderatoesName, username, mode]);
+  return (
+    <SideBarContainer createPost>
+      {!moderate
+      && (
+      <CommunityContainer>
+        <About disc={disc} createdAt={createdAt} num={num} Name={Name} createPost={createPost} />
+      </CommunityContainer>
+      )}
+      {moderate && (
+      <CommunityContainer>
+        <Moderation topics={topics} disc={disc} Name={Name} primaryTopic={primaryTopic} createdAt={createdAt} num={num} createPost={createPost} />
+      </CommunityContainer>
+      )}
+      { (rules?.length > 0)
+     && (
+     <CommunityContainer>
+       <Rules Name={Name} rules={rules} />
+     </CommunityContainer>
+     )}
+      <CommunityContainer>
+        <Flirt />
+      </CommunityContainer>
+      <CommunityContainer sx={{ padding: '0px 12px' }}>
+        <Moderators moderatoesName={finalArray} />
+      </CommunityContainer>
+      {!createPost && <BackHome sx={{ marginTop: -5 }} />}
+    </SideBarContainer>
+  );
+}
+
+export default SideBar;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_SubrridetDataServer.js.html b/docs/components_SubReddit_SubrridetDataServer.js.html new file mode 100644 index 00000000..0db3c9ce --- /dev/null +++ b/docs/components_SubReddit_SubrridetDataServer.js.html @@ -0,0 +1,86 @@ + + + + + JSDoc: Source: components/SubReddit/SubrridetDataServer.js + + + + + + + + + + +
+ +

Source: components/SubReddit/SubrridetDataServer.js

+ + + + + + +
+
+
import { useState, useEffect } from 'react';
+import axios from '../../services/instance';
+/**
+ * get all subreddit data
+ *
+ * @property {string} Name - name of subreddit
+
+ */
+const getSubredditAllData = (Name) => {
+  const [data, setData] = useState(null);
+  const [error, setError] = useState(null);
+  const [statusCode, setStatusCode] = useState(null);
+
+  useEffect(() => {
+    axios.get(`/subreddits/${Name}`).then((response) => {
+      console.log(response);
+
+      setData(response.data);
+      setStatusCode(response.status);
+      // console.log(response.data);
+      setError(null);
+    }).catch((error) => {
+      setError(error);
+      setStatusCode(error.response.status);
+      console.log(error);
+    });
+    if (statusCode === 401 || statusCode === 401) {
+      window.location.pathname = 'login';
+    }
+  }, [Name]);
+  // console.log('hosny', data);
+
+  return [data?.data, error, statusCode];
+};
+export default getSubredditAllData;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_server.js.html b/docs/components_SubReddit_server.js.html new file mode 100644 index 00000000..9f380645 --- /dev/null +++ b/docs/components_SubReddit_server.js.html @@ -0,0 +1,65 @@ + + + + + JSDoc: Source: components/SubReddit/server.js + + + + + + + + + + +
+ +

Source: components/SubReddit/server.js

+ + + + + + +
+
+
import axios from '../../services/instance';
+/**
+ * Join to subreddit
+ *
+ * @property {string} api - url to send data
+ * @property {string} prefs - data to change
+
+ */
+const patchData = (api, prefs) => {
+  axios.patch(`${api}`, prefs).then((response) => response.status).catch((error) => {
+    console.log(error);
+  });
+};
+export default patchData;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_subredditPostsServer.js.html b/docs/components_SubReddit_subredditPostsServer.js.html new file mode 100644 index 00000000..e881122b --- /dev/null +++ b/docs/components_SubReddit_subredditPostsServer.js.html @@ -0,0 +1,132 @@ + + + + + JSDoc: Source: components/SubReddit/subredditPostsServer.js + + + + + + + + + + +
+ +

Source: components/SubReddit/subredditPostsServer.js

+ + + + + + +
+
+
import { useState, useEffect } from 'react';
+import { useListingContext } from '../../contexts/ListingContext';
+import axios from '../../services/instance';
+/**
+ * get Posts to subreddit
+ *
+ * @property {string} Name - name of subreddit
+ * @property {string} postClass - type of posts
+
+ */
+const PostsData = (Name, postClass) => {
+  const [data, setData] = useState(null);
+  const [error, setError] = useState(null);
+  const { page, limit, setPage } = useListingContext();
+
+  useEffect(() => {
+    console.log(postClass);
+
+    axios.get(`/subreddits/${Name}/${postClass || 'hot'}`, {
+      params: {
+        limit,
+        page,
+      },
+    }).then((response) => {
+      console.log(response);
+      if (response?.status === 401) {
+        window.location.pathname = 'login';
+      }
+      console.log('ana geeeet', page, limit);
+      setData((data) => {
+        if (page === 0 || !data) { return response.data; }
+        const tempData = {
+          ...data,
+        };
+        tempData.data = [...tempData.data, ...response.data.data];
+        return tempData;
+      });
+      setError(null);
+    }).catch((error) => {
+      setError(error);
+      console.log(error);
+    });
+  }, [postClass, Name, page, limit]);
+  useEffect(() => {
+    setPage(0);
+    console.log('etghayar');
+  }, [postClass]);
+  console.log('hosny', data);
+  const dbPosts = data?.data;
+  console.log('hosn2', dbPosts);
+  // console.log('from home', statusCode);
+  console.log('posts', dbPosts?.length);
+  const posts = dbPosts?.map((post) => {
+    // for backend bugs
+    const temp = {
+      _id: 1,
+      text: '',
+      backgroundColor: '',
+      textColor: '',
+    };
+    const {
+      text: flairText,
+      backgroundColor: flairBackgroundColor,
+      textColor: flairColor,
+    } = (post.flairId) || temp;
+    const { name: ownerName, icon: ownerIcon } = post.owner;
+    const { name: authorName } = post.author;
+    return ({
+      ...post,
+      flairText,
+      flairBackgroundColor,
+      flairColor,
+      ownerName,
+      ownerIcon,
+      authorName,
+    });
+  });
+  console.log('hosny3', posts);
+  return [{ ...data, data: posts }, error];
+};
+export default PostsData;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/components_SubReddit_subriddetDataModeratorServer.js.html b/docs/components_SubReddit_subriddetDataModeratorServer.js.html new file mode 100644 index 00000000..5a0a77b0 --- /dev/null +++ b/docs/components_SubReddit_subriddetDataModeratorServer.js.html @@ -0,0 +1,83 @@ + + + + + JSDoc: Source: components/SubReddit/subriddetDataModeratorServer.js + + + + + + + + + + +
+ +

Source: components/SubReddit/subriddetDataModeratorServer.js

+ + + + + + +
+
+
import { useState, useEffect } from 'react';
+import axios from '../../services/instance';
+/**
+ * get subreddits which i moderator in
+
+ */
+const useFetch = () => {
+  const [data, setData] = useState(null);
+  const [error, setError] = useState(null);
+  const [statusCode, setStatusCode] = useState(null);
+
+  useEffect(() => {
+    axios.get('/subreddits/mine/subscriber').then((response) => {
+      console.log(response);
+
+      setData(response.data);
+      setStatusCode(response.status);
+      // console.log(response.data);
+      setError(null);
+    }).catch((error) => {
+      setError(error);
+      setStatusCode(error.response.status);
+      console.log(error);
+    });
+    if (statusCode === 401 || statusCode === 401) {
+      window.location.pathname = 'login';
+    }
+  }, []);
+  console.log(data?.data);
+  return [data?.data, error, statusCode];
+};
+export default useFetch;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/contexts_SettingsProvider.js.html b/docs/contexts_SettingsProvider.js.html new file mode 100644 index 00000000..811b3c5f --- /dev/null +++ b/docs/contexts_SettingsProvider.js.html @@ -0,0 +1,79 @@ + + + + + JSDoc: Source: contexts/SettingsProvider.js + + + + + + + + + + +
+ +

Source: contexts/SettingsProvider.js

+ + + + + + +
+
+
import {
+  createContext, useMemo,
+} from 'react';
+
+export const SettingsContext = createContext();
+/**
+ * Settings Provider
+ * provide data prefs
+ * @param {children} - context consumer
+ * @param {object} perfs perfs data
+ * @param {function} setPrefs setPrefs
+ * @returns {React.Context} prefs Provider
+ */
+function SettingsProvider(props) {
+  const {
+    children, prefs, setPrefs,
+  } = props;
+  const value = useMemo(() => ({ prefs, setPrefs }), [prefs, setPrefs]);
+
+  return (
+    <SettingsContext.Provider value={value}>
+      {children}
+    </SettingsContext.Provider>
+
+  );
+}
+
+export default SettingsProvider;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/fonts/OpenSans-Bold-webfont.eot b/docs/fonts/OpenSans-Bold-webfont.eot new file mode 100644 index 00000000..5d20d916 Binary files /dev/null and b/docs/fonts/OpenSans-Bold-webfont.eot differ diff --git a/docs/fonts/OpenSans-Bold-webfont.svg b/docs/fonts/OpenSans-Bold-webfont.svg new file mode 100644 index 00000000..3ed7be4b --- /dev/null +++ b/docs/fonts/OpenSans-Bold-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-Bold-webfont.woff b/docs/fonts/OpenSans-Bold-webfont.woff new file mode 100644 index 00000000..1205787b Binary files /dev/null and b/docs/fonts/OpenSans-Bold-webfont.woff differ diff --git a/docs/fonts/OpenSans-BoldItalic-webfont.eot b/docs/fonts/OpenSans-BoldItalic-webfont.eot new file mode 100644 index 00000000..1f639a15 Binary files /dev/null and b/docs/fonts/OpenSans-BoldItalic-webfont.eot differ diff --git a/docs/fonts/OpenSans-BoldItalic-webfont.svg b/docs/fonts/OpenSans-BoldItalic-webfont.svg new file mode 100644 index 00000000..6a2607b9 --- /dev/null +++ b/docs/fonts/OpenSans-BoldItalic-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-BoldItalic-webfont.woff b/docs/fonts/OpenSans-BoldItalic-webfont.woff new file mode 100644 index 00000000..ed760c06 Binary files /dev/null and b/docs/fonts/OpenSans-BoldItalic-webfont.woff differ diff --git a/docs/fonts/OpenSans-Italic-webfont.eot b/docs/fonts/OpenSans-Italic-webfont.eot new file mode 100644 index 00000000..0c8a0ae0 Binary files /dev/null and b/docs/fonts/OpenSans-Italic-webfont.eot differ diff --git a/docs/fonts/OpenSans-Italic-webfont.svg b/docs/fonts/OpenSans-Italic-webfont.svg new file mode 100644 index 00000000..e1075dcc --- /dev/null +++ b/docs/fonts/OpenSans-Italic-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-Italic-webfont.woff b/docs/fonts/OpenSans-Italic-webfont.woff new file mode 100644 index 00000000..ff652e64 Binary files /dev/null and b/docs/fonts/OpenSans-Italic-webfont.woff differ diff --git a/docs/fonts/OpenSans-Light-webfont.eot b/docs/fonts/OpenSans-Light-webfont.eot new file mode 100644 index 00000000..14868406 Binary files /dev/null and b/docs/fonts/OpenSans-Light-webfont.eot differ diff --git a/docs/fonts/OpenSans-Light-webfont.svg b/docs/fonts/OpenSans-Light-webfont.svg new file mode 100644 index 00000000..11a472ca --- /dev/null +++ b/docs/fonts/OpenSans-Light-webfont.svg @@ -0,0 +1,1831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-Light-webfont.woff b/docs/fonts/OpenSans-Light-webfont.woff new file mode 100644 index 00000000..e7860748 Binary files /dev/null and b/docs/fonts/OpenSans-Light-webfont.woff differ diff --git a/docs/fonts/OpenSans-LightItalic-webfont.eot b/docs/fonts/OpenSans-LightItalic-webfont.eot new file mode 100644 index 00000000..8f445929 Binary files /dev/null and b/docs/fonts/OpenSans-LightItalic-webfont.eot differ diff --git a/docs/fonts/OpenSans-LightItalic-webfont.svg b/docs/fonts/OpenSans-LightItalic-webfont.svg new file mode 100644 index 00000000..431d7e35 --- /dev/null +++ b/docs/fonts/OpenSans-LightItalic-webfont.svg @@ -0,0 +1,1835 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-LightItalic-webfont.woff b/docs/fonts/OpenSans-LightItalic-webfont.woff new file mode 100644 index 00000000..43e8b9e6 Binary files /dev/null and b/docs/fonts/OpenSans-LightItalic-webfont.woff differ diff --git a/docs/fonts/OpenSans-Regular-webfont.eot b/docs/fonts/OpenSans-Regular-webfont.eot new file mode 100644 index 00000000..6bbc3cf5 Binary files /dev/null and b/docs/fonts/OpenSans-Regular-webfont.eot differ diff --git a/docs/fonts/OpenSans-Regular-webfont.svg b/docs/fonts/OpenSans-Regular-webfont.svg new file mode 100644 index 00000000..25a39523 --- /dev/null +++ b/docs/fonts/OpenSans-Regular-webfont.svg @@ -0,0 +1,1831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-Regular-webfont.woff b/docs/fonts/OpenSans-Regular-webfont.woff new file mode 100644 index 00000000..e231183d Binary files /dev/null and b/docs/fonts/OpenSans-Regular-webfont.woff differ diff --git a/docs/global.html b/docs/global.html new file mode 100644 index 00000000..ed20600f --- /dev/null +++ b/docs/global.html @@ -0,0 +1,8334 @@ + + + + + JSDoc: Global + + + + + + + + + + +
+ +

Global

+ + + + + + +
+ +
+ +

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Members

+ + + +

(constant) ApprovedFetch

+ + + + +
+

Function to perfom api request and fetch approved users

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) ApprovedUnapprovedUser

+ + + + +
+

Function to perfom api request. approve or disprove certain user

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) Editban

+ + + + +
+

Function to perfom api request. edit banned user data

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) MuteUnmuteUser

+ + + + +
+

Function to perfom api request. mute or unmute a user

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) ThirdPartyContainer

+ + + + +
+

Box for Third Part Button

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) banUnbanUser

+ + + + +
+

Function to perfom api request. ban or unban certain user

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) bannedFetch

+ + + + +
+

Function to perfom api request. fetch banned user list

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) blockRequest

+ + + + +
+

block a user

+
+ + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
username + + +string + + + +

username of blocked user

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) blockuser

+ + + + +
+
    +
  • Notifications Fetch
  • +
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) checkEmail

+ + + + +
+

Check on Email Format

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) checkEmailToken

+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) checkPassword

+ + + + +
+

check for Password Length more than 7 or not and change state of object atrributes accordingly

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) checkToken

+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) checkUserName

+ + + + +
+

Function to check if length of provided string 3-20 accordingly change color and mesaages of username input field

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) checkUserName

+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) checkUserName

+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) checkUserNameSignUp

+ + + + +
+

check if username length [3-20], if valid username syntax,if username is unique and change state object accordingly

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) checkUserNameSignUp

+ + + + +
+

check if username length [3-20], if valid username syntax,if username is unique and change state object accordingly

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) delMod

+ + + + +
+

Function to perfom api request. remove invitation

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) editMod

+ + + + +
+

Function to perfom api request and Edit moderator data

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) exploreCommunities

+ + + + +
+

Function to perfom api request and fetch communities

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) followRequest

+ + + + +
+

follow a user

+
+ + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
username + + +string + + + +

username of user to be followed

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) getFirebaseToken

+ + + + +
+
    +
  • Get Firebase Token
  • +
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) inviteMod

+ + + + +
+

Function to perfom api request. invite a certain user to the subreddit.

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) logIn

+ + + + +
+

Function Calls /users/login endpoint to Redirect to Home Page or Invalid so Error Messages Appear

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) matchPassword

+ + + + +
+

Check for Passwords matched or not

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) messageSentFetch

+ + + + +
+
    +
  • Messages Fetch
  • +
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) messagesAllServer

+ + + + +
+
    +
  • Notifications Fetch
  • +
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) messagesAllServer

+ + + + +
+
    +
  • Notifications Fetch
  • +
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) messagesServer

+ + + + +
+
    +
  • Notifications Fetch
  • +
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) moderatorsFetch

+ + + + +
+

Function to perfom api request. fetch list of moderators

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) mutedFetch

+ + + + +
+

Function to perfom api request. fetch list of muted users

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) onForegroundNottification

+ + + + +
+
    +
  • on Foreground Nottification
  • +
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) postData

+ + + + +
+
    +
  • Notifications Fetch
  • +
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) recoverPassword

+ + + + +
+

Recover Email

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) recoverPassword

+ + + + +
+

Recover Email

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) recoverUsername

+ + + + +
+

recover Username

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) recoverUsername

+ + + + +
+

recover Username

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) recoverUsername

+ + + + +
+

recover Username

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) redditCookie

+ + + + +
+

Add Reddit Cookie +Must be Authorized user

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) redirectHome

+ + + + +
+

redirect to the home page (./) after time

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) redirectLogin

+ + + + +
+

redirect to the login page (./login) after time

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) removeRedditCookie

+ + + + +
+

Remove Reddit Cookie

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) repliesServer

+ + + + +
+
    +
  • Notifications Fetch
  • +
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) resetPassword

+ + + + +
+

Function to check if length of provided string 3-20 accordingly change color and mesaages of username input field

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) responseFacebook

+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) responseGoogleFail

+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) responseGoogleSuccess

+ + + + +
+

If Valid Token Then user is Logged in and redirected to the homepage

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) settingsPost

+ + + + +
+
    +
  • settings Post data prefs
  • +
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) signUp

+ + + + +
+

SignUp new User Function if there is no a problem with the fields and verification the API is called +else not +Check for the Password Strength +Check if Verified to continue SignUp

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) signUp

+ + + + +
+

SignUp new User Function if there is no a problem with the fields and verification the API is called +else not +Check for the Password Strength +Check if Verified to continue SignUp

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(constant) socialDelete

+ + + + +
+
    +
  • settings Post data prefs
  • +
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +

Methods

+ + + + + + + +

(async) DeleteFlair()

+ + + + + + +
+

Delete Flair

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Name + + +string + + + +

name of subreddit

id + + +integer + + + +

id of flair

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(async) DeleteRule()

+ + + + + + +
+

Delete rule

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Name + + +string + + + +

name of subreddit

id + + +integer + + + +

id of rule

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(async) EditFlair()

+ + + + + + +
+

Edit Flair

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Name + + +string + + + +

name of subreddit

id + + +integer + + + +

id of flair

prefs + + +object + + + +

data to change

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(async) EditRule()

+ + + + + + +
+

Edit rule

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Name + + +string + + + +

name of subreddit

id + + +integer + + + +

id of rule

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

LoadingPage() → {React.Component}

+ + + + + + +
+

Loading Page Component

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Main Body of Loading Page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + + + + + + +

LogIn() → {React.Component}

+ + + + + + +
+

Login Page Component

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Main Body of Login Page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + + + + + + +

(async) PostFlair() → {object}

+ + + + + + +
+

Add New Flair

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
url + + +boolean + + + +

url to send data on

text + + +boolean + + + +

text flair

backgroundColor + + +boolean + + + +

background color for flair

textColor + + +boolean + + + +

text color

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

provided response through backend

+
+ + + +
+
+ Type +
+
+ +object + + +
+
+ + + + + + + + + + + + + +

(async) PostJoin()

+ + + + + + +
+

Join to subreddit

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
url + + +string + + + +

url to send data

action + + +string + + + +

sub / unsub

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(async) PostRule()

+ + + + + + +
+

Post new rule

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
url + + +string + + + +

url to post data

defaultName + + +string + + + +

name for rule

description + + +string + + + +

description of rule

appliesTo + + +string + + + +

applies to in rule

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

PostsData()

+ + + + + + +
+

get Posts to subreddit

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Name + + +string + + + +

name of subreddit

postClass + + +string + + + +

type of posts

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

SettingsProvider(props, perfs, setPrefs) → {React.Context}

+ + + + + + +
+

Settings Provider +provide data prefs

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
props + + +children + + + +

context consumer

perfs + + +object + + + +

perfs data

setPrefs + + +function + + + +

setPrefs

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

prefs Provider

+
+ + + +
+
+ Type +
+
+ +React.Context + + +
+
+ + + + + + + + + + + + + +

SignUpEmail() → {React.Component}

+ + + + + + +
+

SignUp Email Componenet

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + + + + + + +

ThirdPartyButton() → {React.Component}

+ + + + + + +
+

Third Party Button

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

-Third Party Button Styled

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + + + + + + +

calculateTime(time) → {string}

+ + + + + + +
+

This function calculate the relative time between the time the post created at and current time

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
time + + +string + + + +

time in ISO format

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

relative time in specific time unit

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

checkTimeNow() → {Boolean}

+ + + + + + +
+

check Time Now +check if time is today or not

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

main body of navbar in signed out mode

+
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + + + + + + + + + + +

createPostServer()

+ + + + + + +
+

This function works as a server create post page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

createPostServerforSubreddit()

+ + + + + + +
+

This function works as a server create post page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

createPostServerforSubreddit()

+ + + + + + +
+

This function works as a server create post page

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(async) followRequest()

+ + + + + + +
+

Follow

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
username + + +string + + + +

username to send

isFollowed + + +boolean + + + +

name for rule

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

generateRandomUsernamesServer(numberOfGeneratedUsernames, deps) → {Array.<string>}

+ + + + + + +
+

This function works as a server for generating random usernames

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numberOfGeneratedUsernames + + +number + + + +

the maximum number of random usernames to be generated

deps + + +React.State + + + +

the dependencies on which random usernames generated

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

generated usernames

+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

generateRandomUsernamesServer(numberOfGeneratedUsernames, deps) → {Array.<string>}

+ + + + + + +
+

This function works as a server for generating random usernames

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numberOfGeneratedUsernames + + +number + + + +

the maximum number of random usernames to be generated

deps + + +React.State + + + +

the dependencies on which random usernames generated

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

generated usernames

+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

getSubredditAllData()

+ + + + + + +
+

get all subreddit data

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Name + + +string + + + +

name of subreddit

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

iMatcher(value, text) → {boolean}

+ + + + + + +
+

This function check whether some string matches the other one or not

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +string + + + +

text to match with another one

text + + +string + + + +

text to be matched by value

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

number separated with commas

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

notificationsFetch()

+ + + + + + +
+
    +
  • Notifications Fetch
  • +
+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

numberWithCommas(x) → {string}

+ + + + + + +
+

This function convert number from the normal form to comma separated form

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
x + + +number + + + +

number to convert

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

number separated with commas

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

patchData()

+ + + + + + +
+

Join to subreddit

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
api + + +string + + + +

url to send data

prefs + + +string + + + +

data to change

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(async) patchData()

+ + + + + + +
+

edit data for moderation

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Name + + +string + + + +

name of subreddit

prefs + + +object + + + +

data to change

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

renderText() → {string}

+ + + + + + +
+

function to return the empty page text

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
param + + +string + + + +

the subPage of profile

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

text of the empty page

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

replaceDashWithUnderScore(text) → {string}

+ + + + + + +
+

This function replaces each occurence of - (dash) with _ (underscore) in a given text

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
text + + +string + + + +

text to be processed

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

text after processing

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

submitPostServer(post)

+ + + + + + +
+

This function works as a server for submitting post

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
post + + +Object + + + +

post to be posted

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

submitPostServer(post)

+ + + + + + +
+

This function works as a server for submitting post

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
post + + +Object + + + +

post to be posted

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

useFetch()

+ + + + + + +
+

Get flairs for subreddit

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Name + + +string + + + +

name of subreddit

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

useFetch()

+ + + + + + +
+

get subreddits which i moderator in

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/global.html#LogIn b/docs/global.html#LogIn new file mode 100644 index 00000000..745e08ee --- /dev/null +++ b/docs/global.html#LogIn @@ -0,0 +1,194 @@ + + + + + JSDoc: Class: LogIn + + + + + + + + + + +
+ +

Class: LogIn

+ + + + + + +
+ +
+ +

LogIn() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new LogIn() → {React.Component}

+ + + + + + +
+

LogIn popUp

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Main Body of Login Page
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/global.html#SignUpEmail b/docs/global.html#SignUpEmail new file mode 100644 index 00000000..c0426b3a --- /dev/null +++ b/docs/global.html#SignUpEmail @@ -0,0 +1,290 @@ + + + + + JSDoc: Class: SignUpEmail + + + + + + + + + + +
+ +

Class: SignUpEmail

+ + + + + + +
+ +
+ +

SignUpEmail() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new SignUpEmail() → {React.Component}

+ + + + + + +
+

SignUp Username and Password Page View

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
--setUserNamePage + + +function + + + +

setView to Email Page on Back Button Click

--email + + +object + + + +

email taken from user to sign up with

--setEmail + + +function + + + +

set email taken from user

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Email SignUp Component

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/global.html#ThirdPartyButton b/docs/global.html#ThirdPartyButton new file mode 100644 index 00000000..7972ac78 --- /dev/null +++ b/docs/global.html#ThirdPartyButton @@ -0,0 +1,192 @@ + + + + + JSDoc: Class: ThirdPartyButton + + + + + + + + + + +
+ +

Class: ThirdPartyButton

+ + + + + + +
+ +
+ +

ThirdPartyButton() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new ThirdPartyButton() → {React.Component}

+ + + + + + +
+

Third Party Button

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

-Third Party Button Styled

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 00000000..ec416204 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,106 @@ + + + + + JSDoc: Home + + + + + + + + + + +
+ +

Home

+ + + + + + + + +

+ + + + + + + + + + + + + + + +
+

Getting Started with Create React App

+

This project was bootstrapped with Create React App.

+

Available Scripts

+

In the project directory, you can run:

+

npm start

+

Runs the app in the development mode.
+Open http://localhost:3000 to view it in your browser.

+

The page will reload when you make changes.
+You may also see any lint errors in the console.

+

npm test

+

Launches the test runner in the interactive watch mode.
+See the section about running tests for more information.

+

npm run build

+

Builds the app for production to the build folder.
+It correctly bundles React in production mode and optimizes the build for the best performance.

+

The build is minified and the filenames include the hashes.
+Your app is ready to be deployed!

+

See the section about deployment for more information.

+

npm run eject

+

Note: this is a one-way operation. Once you eject, you can't go back!

+

If you aren't satisfied with the build tool and configuration choices, you can eject at any time. This command will remove the single build dependency from your project.

+

Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.

+

You don't have to ever use eject. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.

+

Learn More

+

You can learn more in the Create React App documentation.

+

To learn React, check out the React documentation.

+

Code Splitting

+

This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting

+

Analyzing the Bundle Size

+

This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size

+

Making a Progressive Web App

+

This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app

+

Advanced Configuration

+

This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration

+

Deployment

+

This section has moved here: https://facebook.github.io/create-react-app/docs/deployment

+

npm run build fails to minify

+

This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify

+
+ + + + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/lib_firebase.js.html b/docs/lib_firebase.js.html new file mode 100644 index 00000000..e984f86c --- /dev/null +++ b/docs/lib_firebase.js.html @@ -0,0 +1,103 @@ + + + + + JSDoc: Source: lib/firebase.js + + + + + + + + + + +
+ +

Source: lib/firebase.js

+ + + + + + +
+
+
/* eslint-disable no-unused-vars */
+/* eslint-disable import/no-mutable-exports */
+/* eslint-disable no-promise-executor-return */
+/* eslint-disable no-return-await */
+/* eslint-disable no-restricted-globals */
+import { initializeApp } from 'firebase/app';
+
+import { getFirestore } from '@firebase/firestore';
+import { getMessaging, onMessage, getToken } from 'firebase/messaging';
+
+const firebaseConfig = {
+  apiKey: 'AIzaSyAYaIh5gzJ42Nj_iIevGsh36EuXk14BDqg',
+  authDomain: 'nonlegit-df8a9.firebaseapp.com',
+  projectId: 'nonlegit-df8a9',
+  storageBucket: 'nonlegit-df8a9.appspot.com',
+  messagingSenderId: '82072335604',
+  appId: '1:82072335604:web:fd17be6c3765b21236daa1',
+  measurementId: 'G-4FGQ5GZZFP',
+};
+
+// Initialize Firebase
+export const app = initializeApp(firebaseConfig);
+export const appNottification = initializeApp(firebaseConfig);
+export const firestore = getFirestore(app);
+export const messaging = getMessaging(app);
+// export const messagingNottification = getMessaging(appNottification);
+
+// export const onForegroundMessage = () => new Promise((resolve) => onMessage(messaging, (payload) => resolve(payload)));
+/**
+ * - on Foreground Nottification
+ * @return {Promise} - promise wait massage foreground
+ */
+export const onForegroundNottification = () => new Promise((resolve) => onMessage(messaging, (payload) => resolve(payload)));
+export const getOrRegisterServiceWorker = async () => {
+  if ('serviceWorker' in navigator) {
+    return await window.navigator.serviceWorker
+      .getRegistration('/firebase-push-notification-scope')
+      .then((serviceWorker) => {
+        if (serviceWorker) return serviceWorker;
+        return window.navigator.serviceWorker.register('/firebase-messaging-sw.js', {
+          scope: '/firebase-push-notification-scope',
+        });
+      });
+  }
+  throw new Error('The browser doesn`t support service worker.');
+};
+/**
+ * - Get Firebase Token
+ * @return {Promise} - get token from firebase when asked
+ */
+export const getFirebaseToken = () => getOrRegisterServiceWorker()
+  .then((serviceWorkerRegistration) => getToken(messaging, { vapidKey: 'BLsmD9ZEQyLyHpNKCK0zUjWWkt4LHZLlTP1pkVC_w2QiS_ixyutdofxanfdeoaASHn3j71M0QZUS74s8fikX94M', serviceWorkerRegistration }));
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/module.html#.exports b/docs/module.html#.exports new file mode 100644 index 00000000..b6565865 --- /dev/null +++ b/docs/module.html#.exports @@ -0,0 +1,3568 @@ + + + + + JSDoc: Class: exports + + + + + + + + + + +
+ +

Class: exports

+ + + + + + +
+ +
+ +

exports() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports() → {React.Component}

+ + + + + + +
+

navigation button for explore page between communities and posts

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
title + + +string + + + +

the title of the communities

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • navigation buttons component
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

exports() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports() → {React.Component}

+ + + + + + +
+

Drawer

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

the side bar that permenantely appears on the left on the page +in case of signed out

+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

exports(t, e) → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports(t, e) → {React.Component}

+ + + + + + +
+

Community

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
t + + +string + + + +

the new type of the community

e + + +string + + + +

the input feild which is clicked

+ + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
myType + + +function + + + +

to set the type of the community

check + + +function + + + +

to check if the community name length less than 100

checkDisc + + +function + + + +

to check if the community description length less than 100

redirect + + +function + + + +

to redirect to homepage

createCommunity + + +function + + + +

to show community form

SendData + + +function + + + +

to send new subreddit data to backend

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Community
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

exports() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports() → {React.Component}

+ + + + + + +
+

permissions that tha moderator has

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • permissions that the moderator has
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

exports() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports() → {React.Component}

+ + + + + + +
+

Edit Entity of Flair

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
check + + +function + + + +

copy id

notEmpty + + +function + + + +

check if input feild is empty or not

SendData + + +function + + + +

send data to backend

EditFlair + + +function + + + +

send edited data to backend

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Edit Entity of Flair
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

exports() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports() → {React.Component}

+ + + + + + +
+

New Flair

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
notEmpty + + +function + + + +

check if the input feild is empty or not

SendData + + +function + + + +

send data to backend

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • New Flair
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

exports() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports() → {React.Component}

+ + + + + + +
+

Post Flair

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClick + + +function + + + +

disable all buttoms

trueCan + + +function + + + +

enable all buttoms

save + + +function + + + +

clase form and enable add

cancel + + +function + + + +

clase form and enable add

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Post Flair
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

exports(allowImgs, allowVideos, allowLinks) → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports(allowImgs, allowVideos, allowLinks) → {React.Component}

+ + + + + + +
+

Posts Type

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
allowImgs + + +string + + + +

allow image or not

allowVideos + + +string + + + +

allow video or not

allowLinks + + +string + + + +

allow links or not

+ + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
setallowImgs + + +function + + + +

set allow image or not

setallowVideos + + +function + + + +

set allow image or not

setallowLinks + + +function + + + +

set allow image or not

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Posts Type
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

exports() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports() → {React.Component}

+ + + + + + +
+

Suggestion Sort

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClick1 + + +function + + + +

oggle the list when click

handleClickAway1 + + +function + + + +

handle disable the list when click away

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Suggestion Sort
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

exports() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports() → {React.Component}

+ + + + + + +
+

Add Rule

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClickOpen + + +function + + + +

open rule form

handleClose + + +function + + + +

close rule form

myType + + +function + + + +

set the rule type

check + + +function + + + +

check the title length

check2 + + +function + + + +

check the default name length

check3 + + +function + + + +

check the description length

SendData + + +function + + + +

send data to backend

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Add Rule
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

exports() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports() → {React.Component}

+ + + + + + +
+

Rules

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Rules
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

exports() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports() → {React.Component}

+ + + + + + +
+

Search by posts sort type

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClick + + +function + + + +

navigate and change sort type

showSort + + +function + + + +

show and hide the sort list

handleClickAway + + +function + + + +

close list when click out

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Search by posts sort type
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

exports() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports() → {React.Component}

+ + + + + + +
+

Search by posts time type

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClick + + +function + + + +

navigate and change sort type

showTime + + +function + + + +

show and hide the time list

handleClickAway + + +function + + + +

close list when click out

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Search by posts time type
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +
+ +

exports() → {React.Component}

+ + +
+ +
+
+ + + + + + +

new exports() → {React.Component}

+ + + + + + +
+

More icon

+
+ + + + + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
handleClick1 + + +function + + + +

toggle showList or not

handleClickAway1 + + +function + + + +

handle disable the list when click away

changeFavourit + + +function + + + +

toggle favourit community

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • More icon
  • +
+
+ + + +
+
+ Type +
+
+ +React.Component + + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/pages_LogInPage.jsx.html b/docs/pages_LogInPage.jsx.html new file mode 100644 index 00000000..93cf0f89 --- /dev/null +++ b/docs/pages_LogInPage.jsx.html @@ -0,0 +1,72 @@ + + + + + JSDoc: Source: pages/LogInPage.jsx + + + + + + + + + + +
+ +

Source: pages/LogInPage.jsx

+ + + + + + +
+
+
import { AuthenticationBG, AuthenticationConatiner } from '../components/Authentication/styles';
+import LogIn from '../components/Authentication/LogIn/LogIn';
+
+/**
+ * Component For Login Page Route='/login'
+ * @component
+ * @example
+ * return (
+ *   <LogInPage/>
+ * )
+ */
+function LogInPage() {
+  return (
+    <AuthenticationConatiner data-testid="login-test">
+      <AuthenticationBG />
+      <LogIn />
+    </AuthenticationConatiner>
+  );
+}
+
+export default LogInPage;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/pages_Notifications.jsx.html b/docs/pages_Notifications.jsx.html new file mode 100644 index 00000000..02e11108 --- /dev/null +++ b/docs/pages_Notifications.jsx.html @@ -0,0 +1,71 @@ + + + + + JSDoc: Source: pages/Notifications.jsx + + + + + + + + + + +
+ +

Source: pages/Notifications.jsx

+ + + + + + +
+
+
import MainNotifications from '../components/Notifications/MainNotifications';
+import { ContinerNotifications } from '../components/Notifications/styles';
+
+/**
+ * Notifications page
+ *  @component
+ *
+ * @return {React.Component} - All Notifications page sections
+ */
+
+function Notifications() {
+  return (
+    <ContinerNotifications data-testid="notifications">
+      <MainNotifications />
+
+    </ContinerNotifications>
+  );
+}
+
+export default Notifications;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/scripts/linenumber.js b/docs/scripts/linenumber.js new file mode 100644 index 00000000..4354785c --- /dev/null +++ b/docs/scripts/linenumber.js @@ -0,0 +1,25 @@ +/*global document */ +(() => { + const source = document.getElementsByClassName('prettyprint source linenums'); + let i = 0; + let lineNumber = 0; + let lineId; + let lines; + let totalLines; + let anchorHash; + + if (source && source[0]) { + anchorHash = document.location.hash.substring(1); + lines = source[0].getElementsByTagName('li'); + totalLines = lines.length; + + for (; i < totalLines; i++) { + lineNumber++; + lineId = `line${lineNumber}`; + lines[i].id = lineId; + if (lineId === anchorHash) { + lines[i].className += ' selected'; + } + } + } +})(); diff --git a/docs/scripts/prettify/Apache-License-2.0.txt b/docs/scripts/prettify/Apache-License-2.0.txt new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/docs/scripts/prettify/Apache-License-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/docs/scripts/prettify/lang-css.js b/docs/scripts/prettify/lang-css.js new file mode 100644 index 00000000..041e1f59 --- /dev/null +++ b/docs/scripts/prettify/lang-css.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", +/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/docs/scripts/prettify/prettify.js b/docs/scripts/prettify/prettify.js new file mode 100644 index 00000000..eef5ad7e --- /dev/null +++ b/docs/scripts/prettify/prettify.js @@ -0,0 +1,28 @@ +var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= +[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), +l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, +q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, +"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), +a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} +for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], +H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ +I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), +["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", +/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), +["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", +hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= +!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p th:last-child { border-right: 1px solid #ddd; } + +.ancestors, .attribs { color: #999; } +.ancestors a, .attribs a +{ + color: #999 !important; + text-decoration: none; +} + +.clear +{ + clear: both; +} + +.important +{ + font-weight: bold; + color: #950B02; +} + +.yes-def { + text-indent: -1000px; +} + +.type-signature { + color: #aaa; +} + +.name, .signature { + font-family: Consolas, Monaco, 'Andale Mono', monospace; +} + +.details { margin-top: 14px; border-left: 2px solid #DDD; } +.details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; } +.details dd { margin-left: 70px; } +.details ul { margin: 0; } +.details ul { list-style-type: none; } +.details li { margin-left: 30px; padding-top: 6px; } +.details pre.prettyprint { margin: 0 } +.details .object-value { padding-top: 0; } + +.description { + margin-bottom: 1em; + margin-top: 1em; +} + +.code-caption +{ + font-style: italic; + font-size: 107%; + margin: 0; +} + +.source +{ + border: 1px solid #ddd; + width: 80%; + overflow: auto; +} + +.prettyprint.source { + width: inherit; +} + +.source code +{ + font-size: 100%; + line-height: 18px; + display: block; + padding: 4px 12px; + margin: 0; + background-color: #fff; + color: #4D4E53; +} + +.prettyprint code span.line +{ + display: inline-block; +} + +.prettyprint.linenums +{ + padding-left: 70px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.prettyprint.linenums ol +{ + padding-left: 0; +} + +.prettyprint.linenums li +{ + border-left: 3px #ddd solid; +} + +.prettyprint.linenums li.selected, +.prettyprint.linenums li.selected * +{ + background-color: lightyellow; +} + +.prettyprint.linenums li * +{ + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} + +.params .name, .props .name, .name code { + color: #4D4E53; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + font-size: 100%; +} + +.params td.description > p:first-child, +.props td.description > p:first-child +{ + margin-top: 0; + padding-top: 0; +} + +.params td.description > p:last-child, +.props td.description > p:last-child +{ + margin-bottom: 0; + padding-bottom: 0; +} + +.disabled { + color: #454545; +} diff --git a/docs/styles/prettify-jsdoc.css b/docs/styles/prettify-jsdoc.css new file mode 100644 index 00000000..5a2526e3 --- /dev/null +++ b/docs/styles/prettify-jsdoc.css @@ -0,0 +1,111 @@ +/* JSDoc prettify.js theme */ + +/* plain text */ +.pln { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* string content */ +.str { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a keyword */ +.kwd { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a comment */ +.com { + font-weight: normal; + font-style: italic; +} + +/* a type name */ +.typ { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* a literal value */ +.lit { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* punctuation */ +.pun { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* lisp open bracket */ +.opn { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* lisp close bracket */ +.clo { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a markup tag name */ +.tag { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a markup attribute name */ +.atn { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a markup attribute value */ +.atv { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a declaration */ +.dec { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a variable name */ +.var { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* a function name */ +.fun { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; +} diff --git a/docs/styles/prettify-tomorrow.css b/docs/styles/prettify-tomorrow.css new file mode 100644 index 00000000..b6f92a78 --- /dev/null +++ b/docs/styles/prettify-tomorrow.css @@ -0,0 +1,132 @@ +/* Tomorrow Theme */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* Pretty printing styles. Used with prettify.js. */ +/* SPAN elements with the classes below are added by prettyprint. */ +/* plain text */ +.pln { + color: #4d4d4c; } + +@media screen { + /* string content */ + .str { + color: #718c00; } + + /* a keyword */ + .kwd { + color: #8959a8; } + + /* a comment */ + .com { + color: #8e908c; } + + /* a type name */ + .typ { + color: #4271ae; } + + /* a literal value */ + .lit { + color: #f5871f; } + + /* punctuation */ + .pun { + color: #4d4d4c; } + + /* lisp open bracket */ + .opn { + color: #4d4d4c; } + + /* lisp close bracket */ + .clo { + color: #4d4d4c; } + + /* a markup tag name */ + .tag { + color: #c82829; } + + /* a markup attribute name */ + .atn { + color: #f5871f; } + + /* a markup attribute value */ + .atv { + color: #3e999f; } + + /* a declaration */ + .dec { + color: #f5871f; } + + /* a variable name */ + .var { + color: #c82829; } + + /* a function name */ + .fun { + color: #4271ae; } } +/* Use higher contrast and text-weight for printable form. */ +@media print, projection { + .str { + color: #060; } + + .kwd { + color: #006; + font-weight: bold; } + + .com { + color: #600; + font-style: italic; } + + .typ { + color: #404; + font-weight: bold; } + + .lit { + color: #044; } + + .pun, .opn, .clo { + color: #440; } + + .tag { + color: #006; + font-weight: bold; } + + .atn { + color: #404; } + + .atv { + color: #060; } } +/* Style */ +/* +pre.prettyprint { + background: white; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + font-size: 12px; + line-height: 1.5; + border: 1px solid #ccc; + padding: 10px; } +*/ + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; } + +/* IE indents via margin-left */ +li.L0, +li.L1, +li.L2, +li.L3, +li.L4, +li.L5, +li.L6, +li.L7, +li.L8, +li.L9 { + /* */ } + +/* Alternate shading for lines */ +li.L1, +li.L3, +li.L5, +li.L7, +li.L9 { + /* */ } diff --git a/docs/utils_Redirect.js.html b/docs/utils_Redirect.js.html new file mode 100644 index 00000000..f97fccda --- /dev/null +++ b/docs/utils_Redirect.js.html @@ -0,0 +1,76 @@ + + + + + JSDoc: Source: utils/Redirect.js + + + + + + + + + + +
+ +

Source: utils/Redirect.js

+ + + + + + +
+
+
/**
+ *
+ * redirect to the home page (./) after time
+ * @param {number} time
+ * @returns {void}
+ */
+export const redirectHome = (time) => {
+  setTimeout(() => {
+    // Redirect to home page
+    window.location.pathname = '';
+  }, time);
+};
+
+/**
+ *
+ * redirect to the login page (./login) after time
+ * @param {number} time
+ * @returns {void}
+ */
+export const redirectLogin = (time) => {
+  setTimeout(() => {
+    // Redirect to login page
+    window.location.pathname = 'login';
+  }, time);
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 4.0.0 on Fri Dec 23 2022 20:40:25 GMT+0200 (Eastern European Standard Time) +
+ + + + + diff --git a/docs/utils_calculateTime.js.html b/docs/utils_calculateTime.js.html new file mode 100644 index 00000000..a565d84c --- /dev/null +++ b/docs/utils_calculateTime.js.html @@ -0,0 +1,66 @@ + + + + + JSDoc: Source: utils/calculateTime.js + + + + + + + + + + +
+ +

Source: utils/calculateTime.js

+ + + + + + +
+
+
import moment from 'moment';
+
+/**
+ * This function calculate the relative time between the time the post created at and current time
+ *
+ * @function calculateTime
+ * @param {string} time - time in ISO format
+ * @returns {string} relative time in specific time unit
+ */
+
+function calculateTime(time) {
+  return moment(time).fromNow();
+}
+
+export default calculateTime;
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 4.0.0 on Fri Dec 23 2022 20:40:25 GMT+0200 (Eastern European Standard Time) +
+ + + + + diff --git a/docs/utils_checkTimeNow.js.html b/docs/utils_checkTimeNow.js.html new file mode 100644 index 00000000..5deef08e --- /dev/null +++ b/docs/utils_checkTimeNow.js.html @@ -0,0 +1,60 @@ + + + + + JSDoc: Source: utils/checkTimeNow.js + + + + + + + + + + +
+ +

Source: utils/checkTimeNow.js

+ + + + + + +
+
+
import moment from 'moment/moment';
+
+/**
+ * check Time Now
+ * check if time is today or not
+ * @returns {Boolean} main body of navbar in signed out mode
+ */
+const checkTimeNow = (time) => moment(time).isSame(moment(), 'day');
+export default checkTimeNow;
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 4.0.0 on Fri Dec 23 2022 20:40:25 GMT+0200 (Eastern European Standard Time) +
+ + + + + diff --git a/docs/utils_iMatcher.js.html b/docs/utils_iMatcher.js.html new file mode 100644 index 00000000..fc2760bc --- /dev/null +++ b/docs/utils_iMatcher.js.html @@ -0,0 +1,66 @@ + + + + + JSDoc: Source: utils/iMatcher.js + + + + + + + + + + +
+ +

Source: utils/iMatcher.js

+ + + + + + +
+
+
/**
+ * This function check whether some string matches the other one or not
+ *
+ * @function iMatcher
+ * @param {string} value - text to match with another one
+ * @param {string} text - text to be matched by value
+ * @returns {boolean} number separated with commas
+ */
+
+function iMatcher(text, value) {
+  const regex = new RegExp(value, 'i');
+  return text.match(regex) !== null;
+}
+
+export default iMatcher;
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 4.0.0 on Fri Dec 23 2022 20:40:25 GMT+0200 (Eastern European Standard Time) +
+ + + + + diff --git a/docs/utils_numberWithCommas.js.html b/docs/utils_numberWithCommas.js.html new file mode 100644 index 00000000..985b0c30 --- /dev/null +++ b/docs/utils_numberWithCommas.js.html @@ -0,0 +1,63 @@ + + + + + JSDoc: Source: utils/numberWithCommas.js + + + + + + + + + + +
+ +

Source: utils/numberWithCommas.js

+ + + + + + +
+
+
/**
+ * This function convert number from the normal form to comma separated form
+ *
+ * @function numberWithCommas
+ * @param {number} x - number to convert
+ * @returns {string} number separated with commas
+ */
+
+function numberWithCommas(x) {
+  return x?.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+}
+export default numberWithCommas;
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 4.0.0 on Fri Dec 23 2022 20:40:25 GMT+0200 (Eastern European Standard Time) +
+ + + + + diff --git a/docs/utils_renderText.js.html b/docs/utils_renderText.js.html new file mode 100644 index 00000000..3f60ab05 --- /dev/null +++ b/docs/utils_renderText.js.html @@ -0,0 +1,79 @@ + + + + + JSDoc: Source: utils/renderText.js + + + + + + + + + + +
+ +

Source: utils/renderText.js

+ + + + + + +
+
+
// decide which message to show for an empty page
+/**
+ * function to return the empty page text
+ *
+ * @property {string} param - the subPage of profile
+ * @returns {string} text of the empty page
+ */
+const renderText = (param) => {
+  switch (param) {
+    case 'upvoted':
+      return `hmm...looks like you
+            haven't upvoted and thing yet`;
+    case 'downvoted':
+      return `hmm... looks like you
+            haven't downvoted and thing yet`;
+    case 'saved':
+      return `hmm... looks like you
+            haven't saved and thing yet`;
+    case 'hidden':
+      return `hmm... looks like you
+            haven't hidden and thing yet`;
+
+    default:
+      return 'hmm... looks like you entered a non existing page and thing yet';
+  }
+};
+
+export default renderText;
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 4.0.0 on Fri Dec 23 2022 20:40:25 GMT+0200 (Eastern European Standard Time) +
+ + + + + diff --git a/docs/utils_replaceDashWithUnderScore.js.html b/docs/utils_replaceDashWithUnderScore.js.html new file mode 100644 index 00000000..0a87ab74 --- /dev/null +++ b/docs/utils_replaceDashWithUnderScore.js.html @@ -0,0 +1,62 @@ + + + + + JSDoc: Source: utils/replaceDashWithUnderScore.js + + + + + + + + + + +
+ +

Source: utils/replaceDashWithUnderScore.js

+ + + + + + +
+
+
/**
+ * This function replaces each occurence of - (dash) with _ (underscore) in a given text
+ *
+ * @function replaceDashWithUnderScore
+ * @param {string} text - text to be processed
+ * @returns {string} text after processing
+ */
+
+const replaceDashWithUnderScore = (text) => text.replace(/-/g, '_');
+
+export default replaceDashWithUnderScore;
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 4.0.0 on Fri Dec 23 2022 20:40:25 GMT+0200 (Eastern European Standard Time) +
+ + + + + diff --git a/middleware.ts b/middleware.ts new file mode 100644 index 00000000..017bed07 --- /dev/null +++ b/middleware.ts @@ -0,0 +1,7 @@ +// middleware.ts +module.exports = (req, res, next) => { + if (req.method !== 'GET') { + req.method = 'GET'; + } + next(); +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4ca02f08..f48362c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "draftjs-to-html": "^0.9.1", "firebase": "^9.15.0", "gapi-script": "^1.2.0", + "gh-pages": "^5.0.0", "history": "^5.3.0", "js-cookie": "^3.0.1", "jsdoc-react": "^1.0.0", @@ -118,19 +119,20 @@ } }, "node_modules/@babel/core": { - "version": "7.20.5", - "license": "MIT", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.7.tgz", + "integrity": "sha512-t1ZjCluspe5DW24bn2Rr1CDb2v9rn/hROtg9a2tmd0+QYf4bsloYfLQzjG4qHPNMhWtKdGC33R5AxGR2Af2cBw==", "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-module-transforms": "^7.20.2", - "@babel/helpers": "^7.20.5", - "@babel/parser": "^7.20.5", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5", + "@babel/generator": "^7.20.7", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-module-transforms": "^7.20.7", + "@babel/helpers": "^7.20.7", + "@babel/parser": "^7.20.7", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -169,10 +171,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.20.5", - "license": "MIT", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz", + "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", "dependencies": { - "@babel/types": "^7.20.5", + "@babel/types": "^7.20.7", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -214,12 +217,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.0", - "license": "MIT", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", + "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", "dependencies": { - "@babel/compat-data": "^7.20.0", + "@babel/compat-data": "^7.20.5", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", "semver": "^6.3.0" }, "engines": { @@ -229,6 +234,19 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.20.5", "license": "MIT", @@ -336,17 +354,18 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.20.2", - "license": "MIT", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.7.tgz", + "integrity": "sha512-FNdu7r67fqMUSVuQpFQGE6BPdhJIhitoxhGzDbAXNcA07uoVG37fOiMk3OSV8rEICuyG6t8LGkd9EE64qIEoIA==", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.2" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -464,12 +483,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.20.6", - "license": "MIT", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz", + "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==", "dependencies": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -488,8 +508,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.5", - "license": "MIT", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", + "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -1556,7 +1577,8 @@ }, "node_modules/@babel/preset-env": { "version": "7.20.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", + "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", "dependencies": { "@babel/compat-data": "^7.20.1", "@babel/helper-compilation-targets": "^7.20.0", @@ -1710,29 +1732,31 @@ } }, "node_modules/@babel/template": { - "version": "7.18.10", - "license": "MIT", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.20.5", - "license": "MIT", + "version": "7.20.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.8.tgz", + "integrity": "sha512-/RNkaYDeCy4MjyV70+QkSHhxbvj2JO/5Ft2Pa880qJOG8tWrqcT/wXUuCCv43yogfqPzHL77Xu101KQPf4clnQ==", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", + "@babel/generator": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.5", - "@babel/types": "^7.20.5", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1741,8 +1765,9 @@ } }, "node_modules/@babel/types": { - "version": "7.20.5", - "license": "MIT", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", + "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -6065,6 +6090,14 @@ "node": ">=8" } }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/array.prototype.flat": { "version": "1.3.1", "license": "MIT", @@ -6235,8 +6268,9 @@ }, "node_modules/babel-jest": { "version": "29.3.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.3.1.tgz", + "integrity": "sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==", "dev": true, - "license": "MIT", "dependencies": { "@jest/transform": "^29.3.1", "@types/babel__core": "^7.1.14", @@ -8482,6 +8516,11 @@ "version": "4.12.0", "license": "MIT" }, + "node_modules/email-addresses": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", + "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==" + }, "node_modules/emittery": { "version": "0.13.1", "dev": true, @@ -9724,6 +9763,30 @@ "node": ">=10" } }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/filesize": { "version": "8.0.7", "license": "BSD-3-Clause", @@ -10220,6 +10283,74 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gh-pages": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-5.0.0.tgz", + "integrity": "sha512-Nqp1SjkPIB94Xw/3yYNTUL+G2dxlhjvv1zeN/4kMC1jfViTEqhtVz/Ba1zSXHuvXCN9ADNS1dN4r5/J/nZWEQQ==", + "dependencies": { + "async": "^3.2.4", + "commander": "^2.18.0", + "email-addresses": "^5.0.0", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + }, + "bin": { + "gh-pages": "bin/gh-pages.js", + "gh-pages-clean": "bin/gh-pages-clean.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gh-pages/node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gh-pages/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/gh-pages/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gh-pages/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/glob": { "version": "7.2.3", "license": "ISC", @@ -11357,8 +11488,9 @@ }, "node_modules/jest": { "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.3.1.tgz", + "integrity": "sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==", "dev": true, - "license": "MIT", "dependencies": { "@jest/core": "^29.3.1", "@jest/types": "^29.3.1", @@ -14494,7 +14626,8 @@ }, "node_modules/moment": { "version": "2.29.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", "engines": { "node": "*" } @@ -15114,6 +15247,25 @@ "node": ">=4" } }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/pirates": { "version": "4.0.5", "license": "MIT", @@ -19688,6 +19840,14 @@ "websocket-driver": "^0.7.4" } }, + "node_modules/sockjs/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/source-list-map": { "version": "2.0.1", "license": "MIT" @@ -19965,6 +20125,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-outer/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/style-loader": { "version": "3.3.1", "license": "MIT", @@ -20470,6 +20649,25 @@ "node": ">=12" } }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/trim-repeated/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/tryer": { "version": "1.0.1", "license": "MIT" @@ -20829,13 +21027,6 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "8.3.2", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-to-istanbul": { "version": "9.0.1", "license": "ISC", @@ -21910,18 +22101,20 @@ "version": "7.20.5" }, "@babel/core": { - "version": "7.20.5", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.7.tgz", + "integrity": "sha512-t1ZjCluspe5DW24bn2Rr1CDb2v9rn/hROtg9a2tmd0+QYf4bsloYfLQzjG4qHPNMhWtKdGC33R5AxGR2Af2cBw==", "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-module-transforms": "^7.20.2", - "@babel/helpers": "^7.20.5", - "@babel/parser": "^7.20.5", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5", + "@babel/generator": "^7.20.7", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-module-transforms": "^7.20.7", + "@babel/helpers": "^7.20.7", + "@babel/parser": "^7.20.7", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -21943,9 +22136,11 @@ } }, "@babel/generator": { - "version": "7.20.5", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz", + "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", "requires": { - "@babel/types": "^7.20.5", + "@babel/types": "^7.20.7", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -21974,12 +22169,30 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.20.0", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", + "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", "requires": { - "@babel/compat-data": "^7.20.0", + "@babel/compat-data": "^7.20.5", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", "semver": "^6.3.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } } }, "@babel/helper-create-class-features-plugin": { @@ -22047,16 +22260,18 @@ } }, "@babel/helper-module-transforms": { - "version": "7.20.2", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.7.tgz", + "integrity": "sha512-FNdu7r67fqMUSVuQpFQGE6BPdhJIhitoxhGzDbAXNcA07uoVG37fOiMk3OSV8rEICuyG6t8LGkd9EE64qIEoIA==", "requires": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.2" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" } }, "@babel/helper-optimise-call-expression": { @@ -22124,11 +22339,13 @@ } }, "@babel/helpers": { - "version": "7.20.6", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz", + "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==", "requires": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" } }, "@babel/highlight": { @@ -22140,7 +22357,9 @@ } }, "@babel/parser": { - "version": "7.20.5" + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", + "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.18.6", @@ -22687,6 +22906,8 @@ }, "@babel/preset-env": { "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", + "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", "requires": { "@babel/compat-data": "^7.20.1", "@babel/helper-compilation-targets": "^7.20.0", @@ -22808,30 +23029,36 @@ } }, "@babel/template": { - "version": "7.18.10", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "requires": { "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" } }, "@babel/traverse": { - "version": "7.20.5", + "version": "7.20.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.8.tgz", + "integrity": "sha512-/RNkaYDeCy4MjyV70+QkSHhxbvj2JO/5Ft2Pa880qJOG8tWrqcT/wXUuCCv43yogfqPzHL77Xu101KQPf4clnQ==", "requires": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", + "@babel/generator": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.5", - "@babel/types": "^7.20.5", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.20.5", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", + "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", "requires": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -25457,6 +25684,11 @@ "array-union": { "version": "2.1.0" }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==" + }, "array.prototype.flat": { "version": "1.3.1", "requires": { @@ -25560,6 +25792,8 @@ }, "babel-jest": { "version": "29.3.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.3.1.tgz", + "integrity": "sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==", "dev": true, "requires": { "@jest/transform": "^29.3.1", @@ -27000,6 +27234,11 @@ } } }, + "email-addresses": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", + "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==" + }, "emittery": { "version": "0.13.1", "dev": true @@ -27797,6 +28036,21 @@ } } }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==" + }, + "filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + } + }, "filesize": { "version": "8.0.7" }, @@ -28092,6 +28346,57 @@ "get-intrinsic": "^1.1.1" } }, + "gh-pages": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-5.0.0.tgz", + "integrity": "sha512-Nqp1SjkPIB94Xw/3yYNTUL+G2dxlhjvv1zeN/4kMC1jfViTEqhtVz/Ba1zSXHuvXCN9ADNS1dN4r5/J/nZWEQQ==", + "requires": { + "async": "^3.2.4", + "commander": "^2.18.0", + "email-addresses": "^5.0.0", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + }, + "dependencies": { + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "requires": { + "array-uniq": "^1.0.1" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" + } + } + }, "glob": { "version": "7.2.3", "requires": { @@ -28748,6 +29053,8 @@ }, "jest": { "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.3.1.tgz", + "integrity": "sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==", "dev": true, "requires": { "@jest/core": "^29.3.1", @@ -30780,7 +31087,9 @@ "dev": true }, "moment": { - "version": "2.29.4" + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, "morgan": { "version": "1.10.0", @@ -31148,6 +31457,19 @@ "pify": { "version": "3.0.0" }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "requires": { + "pinkie": "^2.0.0" + } + }, "pirates": { "version": "4.0.5" }, @@ -33892,6 +34214,13 @@ "faye-websocket": "^0.11.3", "uuid": "^8.3.2", "websocket-driver": "^0.7.4" + }, + "dependencies": { + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + } } }, "source-list-map": { @@ -34074,6 +34403,21 @@ "strip-json-comments": { "version": "3.1.1" }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "requires": { + "escape-string-regexp": "^1.0.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + } + } + }, "style-loader": { "version": "3.3.1" }, @@ -34382,6 +34726,21 @@ "punycode": "^2.1.1" } }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "requires": { + "escape-string-regexp": "^1.0.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + } + } + }, "tryer": { "version": "1.0.1" }, @@ -34592,9 +34951,6 @@ "utils-merge": { "version": "1.0.1" }, - "uuid": { - "version": "8.3.2" - }, "v8-to-istanbul": { "version": "9.0.1", "requires": { diff --git a/package.json b/package.json index 98adfbb4..60bf4d2f 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,5 @@ { + "homepage": "http://NonLegit.github.io/", "name": "reddit", "version": "0.1.0", "private": true, @@ -26,6 +27,7 @@ "draftjs-to-html": "^0.9.1", "firebase": "^9.15.0", "gapi-script": "^1.2.0", + "gh-pages": "^5.0.0", "history": "^5.3.0", "js-cookie": "^3.0.1", "jsdoc-react": "^1.0.0", @@ -63,11 +65,13 @@ }, "scripts": { "start": "react-scripts start", + "predeploy":"npm run build", + "deploy":"gh-pages -d build", "build": "react-scripts build", "test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!axios)/\" ", "eject": "react-scripts eject", "docs": "jsdoc -c jsdoc.json", - "server-json": "json-server --watch data/index.js --port 8000 --routes data/routes.json" + "server-json": "json-server --watch data/index.js --port 8000 --routes data/routes.json --middlewares middleware.ts" }, "eslintConfig": { "extends": [ diff --git a/public/firebase-messaging-sw.js b/public/firebase-messaging-sw.js index 0bfc8568..cf271322 100644 --- a/public/firebase-messaging-sw.js +++ b/public/firebase-messaging-sw.js @@ -54,12 +54,18 @@ const follwed = (ele) => { messaging.onBackgroundMessage((payload) => { console.log('Received background message: ', payload); const { data: { val } } = payload; - + const value = JSON.parse(val); + let notificationOptions; const notificationTitle = 'New Notifications !!'; + if (value.type === 'postReply' || value.type === 'follow' || value.type === 'commentReply' || value.type === 'userMention' || value.type === 'firstPostUpVote' || value.type === 'firstCommentUpVote') { + notificationOptions = { + body: follwed(value), - const notificationOptions = { - body: follwed(JSON.parse(val)), + }; + } else { + notificationOptions = { + body: 'you Have new message', - }; - self.registration.showNotification(notificationTitle, notificationOptions); + }; + }self.registration.showNotification(notificationTitle, notificationOptions); }); diff --git a/src/App.jsx b/src/App.jsx index 500b94a0..6a165b82 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -27,15 +27,20 @@ import ForgetPasswordPage from './pages/ForgetPasswordPage'; import ResetPasswordPage from './pages/ResetPasswordPage'; import HomePage from './pages/HomePage'; -import Messages from './pages/Messages'; +import MessageForm from './components/Messages/MessageForm/MessageForm'; +import MessageSent from './components/Messages/MessageSent/MessageSent'; +import MessagesAll from './components/Messages/MessagesAll/MessagesAll'; +import MessagesUnread from './components/Messages/MessagesUnread/MessagesUnread'; +import MessagesDrive from './components/Messages/MessagesDrive/MessagesDrive'; +import PostReplies from './components/Messages/PostReplies/PostReplies'; import Moderation from './pages/Moderation'; +import Messages from './pages/Messages'; import Profile from './pages/Profile'; import Search from './pages/Search'; import CreatePost from './pages/CreatePost'; import PostTypeContextProvider from './contexts/PostTypeContext'; import Notifications from './pages/Notifications'; import SubReddit from './pages/SubReddit'; -import Explore from './pages/Explore'; import { getFirebaseToken } from './lib/firebase'; import MainProfile from './components/MainProfile/MainProfile'; @@ -46,12 +51,15 @@ import EditPostContextProvider from './contexts/EditPostContext'; import { notificationToken } from './services/notificationToken'; import AllPage from './pages/AllPage'; import CreatePostSidebarContextProvider from './contexts/CreatePostSidebarContext'; +import ErrorPage from './pages/ErrorPage'; +import VerifyEmailPage from './pages/VerifyEmailPage'; +import Explore from './pages/Explore'; function App() { // eslint-disable-next-line no-unused-vars const [cookies, setCookies, removeCookie] = useCookies(['redditUser']); - const [showNotificationBanner, setShowNotificationBanner] = useState(false);// Notification.permission === 'default' + const [showNotificationBanner, setShowNotificationBanner] = useState(Notification.permission === 'default'); const handleGetFirebaseToken = () => { if (showNotificationBanner) { getFirebaseToken() @@ -74,7 +82,6 @@ function App() { return ( - @@ -84,296 +91,124 @@ function App() { - - } - /> - - } - > - - } - /> + } /> + }> + } /> - - } - /> - - } - /> - - } - /> - - } - /> - - } - /> - - } - /> - - } - > - - - } - /> - - - } - /> - - } - /> + } /> + } /> + } /> + } /> + } /> + } /> + }> + } /> + + } /> + } /> - - } - /> - - } - /> - - } - /> - - } - /> + } /> + } /> + } /> + } /> + } /> + } /> - } - /> - - } - /> - - } - /> - - - } - /> - - - } - /> - - } - /> - - } - /> - - - } - /> - - - } + } > - } - /> - - } - /> - - - } + + } /> - - - - } - > - } + + } /> - } + + } /> - } + + } /> - } + + } /> - } + + } /> - - } - > - - } - /> + } /> + + } /> + } /> + } /> + + } /> + + }> + } /> + } /> + } /> + } /> + } /> + + + }> + } /> + }> + }> + {/* }> + } /> + } /> } + */} + } /> + + + + } /> + } /> - } + + } /> - - )} - > - - - } - > - - } - /> - - {/* - } - > - + } + /> + - } - /> - */} - - - } - /> - - - - + + } + /> @@ -381,7 +216,6 @@ function App() { - ); } diff --git a/src/authentication.js b/src/authentication.js index daaba063..5d656773 100644 --- a/src/authentication.js +++ b/src/authentication.js @@ -1,10 +1,12 @@ import { useEffect } from 'react'; import { useCookies } from 'react-cookie'; import { redditCookie } from './components/Authentication/authenticationServer'; - +/** + * - UserLogin to check if usenae and give permissions to him or not + */ export default function UserLogin(arr) { - const [cookies, setCookies] = useCookies(['redditUser']); - useEffect(() => { redditCookie(setCookies); }, []); + const [cookies, setCookies, removeCookie] = useCookies(['redditUser']); + useEffect(() => { redditCookie(setCookies, removeCookie); }, []); const userName = (cookies.redditUser?.userName); // console.log(userName, arr); diff --git a/src/components/AlertMessage.js b/src/components/AlertMessage.js new file mode 100644 index 00000000..ef0ea973 --- /dev/null +++ b/src/components/AlertMessage.js @@ -0,0 +1,3 @@ +export default function Done(message) { + alert(message); +} diff --git a/src/components/All/AllContainer/AllContainer.test.jsx b/src/components/All/AllContainer/AllContainer.test.jsx new file mode 100644 index 00000000..9c26fa9e --- /dev/null +++ b/src/components/All/AllContainer/AllContainer.test.jsx @@ -0,0 +1,37 @@ +import renderer from 'react-test-renderer'; +import { ThemeProvider } from '@mui/system'; +import { MemoryRouter as Router } from 'react-router-dom'; +import AllContainer from './AllContainer'; +import ListingContextProvider from '../../../contexts/ListingContext'; +import theme from '../../../styles/theme'; +import PostTypeContextProvider from '../../../contexts/PostTypeContext'; +import HiddenPostsContextProvider from '../../../contexts/HiddenPostsContext'; +import EditPostContextProvider from '../../../contexts/EditPostContext'; +import CreatePostSidebarContextProvider from '../../../contexts/CreatePostSidebarContext'; + +describe(AllContainer, () => { + it('AllContainer renders correctly', () => { + const tree = renderer + .create( + + + + + + + + + + + + + + + + , + + ) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/components/All/AllContainer/__snapshots__/AllContainer.test.jsx.snap b/src/components/All/AllContainer/__snapshots__/AllContainer.test.jsx.snap new file mode 100644 index 00000000..5783ce6d --- /dev/null +++ b/src/components/All/AllContainer/__snapshots__/AllContainer.test.jsx.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AllContainer AllContainer renders correctly 1`] = ` +
+
+
+
+
+
+
+`; diff --git a/src/components/Authentication/FirstParty/FirstParty.jsx b/src/components/Authentication/FirstParty/FirstParty.jsx index 9b78d16e..f33c5c31 100644 --- a/src/components/Authentication/FirstParty/FirstParty.jsx +++ b/src/components/Authentication/FirstParty/FirstParty.jsx @@ -34,10 +34,10 @@ function FirstParty() { // useCookies // eslint-disable-next-line no-unused-vars - const [cookies, setCookies] = useCookies(['redditUser']); + const [cookies, setCookies, removeCookie] = useCookies(['redditUser']); return ( - { logIn(e, setLoading, userName, password, setPassword, setButtonText, setDisabled, setRedirectCaption, setCookies, setUserName); }} data-testid="FirstParty-test"> + { logIn(e, setLoading, userName, password, setPassword, setButtonText, setDisabled, setRedirectCaption, setCookies, removeCookie, setUserName); }} data-testid="FirstParty-test"> { - console.log(response); + console.log('login Response', response); if (response.status === 200 || response.status === 201) { setLoading(false); setButtonText(); setDisabled(true); setRedirectCaption(true); // Add Reddit Cookie - if (popUp === false) { console.log('popup'); redditCookie(setCookies); redirectHome(1000); } else { + if (popUp === false) { + console.log('popup'); + redditCookie(setCookies, removeCookie); + redirectHome(1000); + } else { // PopUp window const interval = setInterval(() => { handleClose(); - redditCookie(setCookies); + redditCookie(setCookies, removeCookie); clearInterval(interval); }, 1000); } diff --git a/src/components/Authentication/ForgetPassword/ForgetPassword.jsx b/src/components/Authentication/ForgetPassword/ForgetPassword.jsx index a44a4268..2bdcf993 100644 --- a/src/components/Authentication/ForgetPassword/ForgetPassword.jsx +++ b/src/components/Authentication/ForgetPassword/ForgetPassword.jsx @@ -28,7 +28,7 @@ import { redditCookie, checkEmail } from '../authenticationServer'; * Component for Forget Password Page * * @component - * @returns {React.Component} --ForgetPassword Page Component + * @returns {React.Component} --ForgetPassword Component */ function ForgetPassword() { // states diff --git a/src/components/Authentication/ForgetPassword/ForgetPassword.test.jsx b/src/components/Authentication/ForgetPassword/ForgetPassword.test.jsx index cda47261..273e1403 100644 --- a/src/components/Authentication/ForgetPassword/ForgetPassword.test.jsx +++ b/src/components/Authentication/ForgetPassword/ForgetPassword.test.jsx @@ -3,20 +3,20 @@ import { } from '@testing-library/react'; import renderer from 'react-test-renderer'; import '@testing-library/jest-dom'; -import App from '../../../App'; +// import App from '../../../App'; import ForgetPassword from './ForgetPassword'; // render forget password page it('should render Forget password page', () => { window.history.pushState({}, '', '/password'); - render(); + render(); expect(screen.queryByTestId('forgetpassword-test')).toBeInTheDocument(); }); // Empty Fields it('Empty Fields Keeps view on Forget password Page', () => { window.history.pushState({}, '', '/password'); - render(); + render(); expect(screen.queryByTestId('forgetpassword-test')).toBeInTheDocument(); const resetbtn = screen.getByTestId('reset-password-btn-test'); @@ -29,7 +29,7 @@ it('Empty Fields Keeps view on Forget password Page', () => { it('Invlaid UserName', () => { window.history.pushState({}, '', '/password'); - render(); + render(); const field1 = screen.getByTestId('forgetpassword-username-input').querySelector('input'); expect(field1).toBeInTheDocument(); fireEvent.change(field1, { target: { value: 'a' } }); @@ -43,7 +43,7 @@ it('Invlaid UserName', () => { it('Invlaid Email', () => { window.history.pushState({}, '', '/password'); - render(); + render(); const field1 = screen.getByTestId('forgetpassword-email-input').querySelector('input'); expect(field1).toBeInTheDocument(); fireEvent.change(field1, { target: { value: 'Bamsa_Elhoseny' } }); @@ -59,7 +59,7 @@ it('Invlaid Email', () => { it('Valid inpts', () => { window.history.pushState({}, '', '/password'); - render(); + render(); const field1 = screen.getByTestId('forgetpassword-username-input').querySelector('input'); expect(field1).toBeInTheDocument(); fireEvent.change(field1, { target: { value: 'Basma_Elhoseny01' } }); diff --git a/src/components/Authentication/ForgetUsername/ForgetUsername.test.jsx b/src/components/Authentication/ForgetUsername/ForgetUsername.test.jsx index e7915f0b..aa6b6917 100644 --- a/src/components/Authentication/ForgetUsername/ForgetUsername.test.jsx +++ b/src/components/Authentication/ForgetUsername/ForgetUsername.test.jsx @@ -1,46 +1,6 @@ -import { - screen, render, fireEvent, -} from '@testing-library/react'; import renderer from 'react-test-renderer'; import '@testing-library/jest-dom'; import ForgetUsername from './ForgetUsername'; -import App from '../../../App'; - -// render forget username page -it('should render Forget username page', () => { - window.history.pushState({}, '', '/username'); - render(); - expect(screen.queryByTestId('forgetusername-test')).toBeInTheDocument(); -}); - -// Empty Email Field -it('Empty Email Field Keeps view on ForgetUsername Page', () => { - window.history.pushState({}, '', '/username'); - render(); - expect(screen.queryByTestId('forgetusername-test')).toBeInTheDocument(); - - const emailbtn = screen.getByTestId('email-btn-test'); - fireEvent.click(emailbtn); - setTimeout(() => { - expect(screen.queryByTestId('forgetusername-test')).toBeInTheDocument(); - expect(screen.queryByTestId('forgetusername-redirect-caption-test')).toBeNull(); - }, 5000); -}); - -it('Invlaid Email', () => { - window.history.pushState({}, '', '/username'); - render(); - const field1 = screen.getByTestId('SignUpEmail-test').querySelector('input'); - expect(field1).toBeInTheDocument(); - fireEvent.change(field1, { target: { value: 'Bamsa_Elhoseny' } }); - - const emailbtn = screen.getByTestId('email-btn-test'); - expect(emailbtn).toBeInTheDocument(); - fireEvent.click(emailbtn); - - // The Email isn't Valid - expect(screen.queryByText('Please fix your email to continue')).toBeInTheDocument(); -}); // test snapshot test('ForgetUsername-test-snapshot', async () => { diff --git a/src/components/Authentication/ForgetUsername/forgetUsernameServer.js b/src/components/Authentication/ForgetUsername/forgetUsernameServer.js index a6536712..571d6693 100644 --- a/src/components/Authentication/ForgetUsername/forgetUsernameServer.js +++ b/src/components/Authentication/ForgetUsername/forgetUsernameServer.js @@ -34,9 +34,10 @@ export const recoverUsername = ( return; } + console.log('Calling'); // Accepted Call API axios.post('/users/forgot_username', { email: email.input }).then((response) => { - // console.log(response); + console.log(response); if (response.status === 204 || response.status === 201 || response.status === 200) { setTimeout(() => { setLoading(false); diff --git a/src/components/Authentication/LogIn/LogIn.jsx b/src/components/Authentication/LogIn/LogIn.jsx index db59c3a7..519265e5 100644 --- a/src/components/Authentication/LogIn/LogIn.jsx +++ b/src/components/Authentication/LogIn/LogIn.jsx @@ -1,3 +1,4 @@ +/* eslint-disable no-unused-vars */ import { useEffect, useState } from 'react'; import { useCookies } from 'react-cookie'; diff --git a/src/components/Authentication/Redirect.test.js b/src/components/Authentication/Redirect.test.js new file mode 100644 index 00000000..b304760d --- /dev/null +++ b/src/components/Authentication/Redirect.test.js @@ -0,0 +1,16 @@ +import '@testing-library/jest-dom'; +import { redirectHome, redirectLogin } from '../../utils/Redirect'; + +it('Redirect To home page', () => { + redirectHome(0); + setTimeout(() => { + expect(global.window.location.pathname).toBe('/'); + }, 50); +}); + +it('Redirect To Login page', () => { + redirectLogin(0); + setTimeout(() => { + expect(global.window.location.pathname).tobe('/login'); + }, 50); +}); diff --git a/src/components/Authentication/ResetPassword/ResetPassword.test.jsx b/src/components/Authentication/ResetPassword/ResetPassword.test.jsx index 1cf54f8c..edb174e2 100644 --- a/src/components/Authentication/ResetPassword/ResetPassword.test.jsx +++ b/src/components/Authentication/ResetPassword/ResetPassword.test.jsx @@ -3,20 +3,20 @@ import { } from '@testing-library/react'; import renderer from 'react-test-renderer'; import '@testing-library/jest-dom'; -import App from '../../../App'; + import ResetPassword from './ResetPassword'; // render forget password page it('should render Reset password page', () => { window.history.pushState({}, '', '/resetpassword/123466Fadsfgkvbnm'); - render(); + render(); expect(screen.queryByTestId('resetpassword-test')).toBeInTheDocument(); }); // Empty Fields it('Empty Fields Keeps view on Reset password Page', () => { window.history.pushState({}, '', '/resetpassword/123466Fadsfgkvbnm'); - render(); + render(); expect(screen.queryByTestId('resetpassword-test')).toBeInTheDocument(); const resetbtn = screen.getByTestId('set-newpassword-btn-test'); @@ -29,7 +29,7 @@ it('Empty Fields Keeps view on Reset password Page', () => { it('Short Password', () => { window.history.pushState({}, '', '/resetpassword/123466Fadsfgkvbnm'); - render(); + render(); const field1 = screen.getByTestId('resetpassword-password-input').querySelector('input'); expect(field1).toBeInTheDocument(); fireEvent.change(field1, { target: { value: 'Basma@1' } }); @@ -43,7 +43,7 @@ it('Short Password', () => { it('Mismatched Passwords', () => { window.history.pushState({}, '', '/resetpassword/123466Fadsfgkvbnm'); - render(); + render(); // Password const field1 = screen.getByTestId('resetpassword-password-input').querySelector('input'); expect(field1).toBeInTheDocument(); @@ -63,7 +63,7 @@ it('Mismatched Passwords', () => { it('Invalid Token', () => { window.history.pushState({}, '', '/resetpassword/123466Fadsfgkvbnm'); - render(); + render(); // Password const field1 = screen.getByTestId('resetpassword-password-input').querySelector('input'); expect(field1).toBeInTheDocument(); @@ -85,7 +85,7 @@ it('Invalid Token', () => { it('Weak Password', () => { window.history.pushState({}, '', '/resetpassword/123466Fadsfgkvbnm'); - render(); + render(); // Password const field1 = screen.getByTestId('resetpassword-password-input').querySelector('input'); expect(field1).toBeInTheDocument(); diff --git a/src/components/Authentication/SignUp/SignUp.jsx b/src/components/Authentication/SignUp/SignUp.jsx index 632795e7..50786210 100644 --- a/src/components/Authentication/SignUp/SignUp.jsx +++ b/src/components/Authentication/SignUp/SignUp.jsx @@ -1,6 +1,5 @@ import { useEffect, useState } from 'react'; import { useCookies } from 'react-cookie'; -// import Cookies from 'js-cookie'; // components import SignUpEmail from './SignUpEmail/SignUpEmail'; @@ -15,9 +14,6 @@ import theme from '../../../styles/theme'; import { redditCookie } from '../authenticationServer'; -// environment variables -// const { REACT_APP_ENV } = process.env; - /** * SignUp Page Main Componnet with 2 view one for the Email and the Other for the userName * @@ -67,7 +63,7 @@ function SignUp() { }, []); const signUpView = userNamePage - ? + ? : ; return ( diff --git a/src/components/Authentication/SignUp/SignUp.test.jsx b/src/components/Authentication/SignUp/SignUp.test.jsx index 82dfbe8a..5c3eed5f 100644 --- a/src/components/Authentication/SignUp/SignUp.test.jsx +++ b/src/components/Authentication/SignUp/SignUp.test.jsx @@ -1,20 +1,20 @@ import '@testing-library/jest-dom'; import renderer from 'react-test-renderer'; import { render, screen, fireEvent } from '@testing-library/react'; -import App from '../../../App'; + import SignUp from './SignUp'; // render signup page it('should render Signup page', () => { window.history.pushState({}, '', '/register'); - render(); + render(); expect(screen.queryByTestId('signup-test')).toBeInTheDocument(); }); // Empty Email Field View is SignUpEmail not SignUpUsername it('Empty Email Field Keeps view on SigUpEmail Page', () => { window.history.pushState({}, '', '/register'); - render(); + render(); expect(screen.queryByTestId('signup-test')).toBeInTheDocument(); const emailbtn = screen.getByTestId('email-btn-test'); @@ -26,7 +26,7 @@ it('Empty Email Field Keeps view on SigUpEmail Page', () => { // Invalid Email Field View is SignUpEmail not SignUpUsername it('InValid Email Field Keeps view on SigUpEmail Page', () => { window.history.pushState({}, '', '/register'); - render(); + render(); expect(screen.queryByTestId('signup-test')).toBeInTheDocument(); const emailfield = screen.queryByTestId('SignUpEmail-test').querySelector('input'); @@ -42,7 +42,7 @@ it('InValid Email Field Keeps view on SigUpEmail Page', () => { // valid Email Field changes the View to be SignUpUsername not SignUpEmail it('Valid Email Field changes view to SignUpUsername Page', () => { window.history.pushState({}, '', '/register'); - render(); + render(); expect(screen.queryByTestId('signup-test')).toBeInTheDocument(); const emailfield = screen.queryByTestId('SignUpEmail-test').querySelector('input'); diff --git a/src/components/Authentication/SignUp/SignUpUsername/SignUpUsername.jsx b/src/components/Authentication/SignUp/SignUpUsername/SignUpUsername.jsx index 7a5b1336..be9b12f9 100644 --- a/src/components/Authentication/SignUp/SignUpUsername/SignUpUsername.jsx +++ b/src/components/Authentication/SignUp/SignUpUsername/SignUpUsername.jsx @@ -41,7 +41,7 @@ const { REACT_APP_SITEKEY } = process.env; * @returns {React.Component} UserName and Password Form */ function SignUpUsername({ - setUserNamePage, email, userName, setUserName, password, setPassword, setCookies, + setUserNamePage, email, userName, setUserName, password, setPassword, setCookies, removeCookie, }) { // states const [defaultUserNameValue, setdefaultUserNameValue] = useState(userName?.input); @@ -59,7 +59,7 @@ function SignUpUsername({ const signUpFunction = () => { checkUserNameSignUp(userName?.input, setUserName); checkPassword(password?.input, setPassword, password); - signUp(email, userName, setUserName, password, setPassword, verified, setLoading, setButtonText, setDisabled, setRedirectCaption, setCookies); + signUp(email, userName, setUserName, password, setPassword, verified, setLoading, setButtonText, setDisabled, setRedirectCaption, setCookies, removeCookie); }; return ( diff --git a/src/components/Authentication/SignUp/SignUpUsername/SignUpUsername.test.jsx b/src/components/Authentication/SignUp/SignUpUsername/SignUpUsername.test.jsx index 3dccba0e..a6a422cf 100644 --- a/src/components/Authentication/SignUp/SignUpUsername/SignUpUsername.test.jsx +++ b/src/components/Authentication/SignUp/SignUpUsername/SignUpUsername.test.jsx @@ -1,8 +1,9 @@ -import replaceDashWithUnderScore from '../../../../utils/replaceDashWithUnderScore'; import '@testing-library/jest-dom'; -// import renderer from 'react-test-renderer'; -// import SignUp from '../SignUp'; -// import SignUpUsername from './SignUpUsername'; +import renderer from 'react-test-renderer'; +import SignUp from '../SignUp'; +import SignUpUsername from './SignUpUsername'; + +import replaceDashWithUnderScore from '../../../../utils/replaceDashWithUnderScore'; // Testing Generate user Name describe(replaceDashWithUnderScore, () => { @@ -58,8 +59,8 @@ describe(replaceDashWithUnderScore, () => { }); }); -// // test snapshot -// test('SigUp test snapshot', async () => { -// const tree = renderer.create().toJSON(); -// expect(tree).toMatchSnapshot(); -// }); +// test snapshot +test('SigUp test snapshot', async () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/Authentication/SignUp/SignUpUsername/__snapshots__/SignUpUsername.test.jsx.snap b/src/components/Authentication/SignUp/SignUpUsername/__snapshots__/SignUpUsername.test.jsx.snap new file mode 100644 index 00000000..614015b7 --- /dev/null +++ b/src/components/Authentication/SignUp/SignUpUsername/__snapshots__/SignUpUsername.test.jsx.snap @@ -0,0 +1,212 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SigUp test snapshot 1`] = ` +
+
+
+
+

+ Sign up +

+

+ By continuing, you are setting up a Reddit account and agree to our + + + User Agreement + + + and + + + Privacy Policy + + . +

+
+
+ + +
+
+
+

+ OR +

+
+
+
+
+ +
+ +
+
+ +
+

+ Already a redditor? + + + log in + +

+
+
+`; diff --git a/src/components/Authentication/SignUp/SignUpUsername/server.js b/src/components/Authentication/SignUp/SignUpUsername/server.js index 5b9d028b..7feb148f 100644 --- a/src/components/Authentication/SignUp/SignUpUsername/server.js +++ b/src/components/Authentication/SignUp/SignUpUsername/server.js @@ -12,7 +12,7 @@ import { wrongIcon, rightIcon } from '../../styles'; import theme from '../../../../styles/theme/index'; // Scripts -import { redditCookie } from '../../scripts'; +import { redditCookie } from '../../authenticationServer'; import { redirectHome } from '../../../../utils/Redirect'; // utils @@ -104,6 +104,7 @@ export const signUp = ( setDisabled, setRedirectCaption, setCookies, + removeCookie, popUp = false, handleClose = null, ) => { @@ -155,10 +156,10 @@ export const signUp = ( setRedirectCaption(true); // Add Reddit Cookie - if (popUp === false) { redirectHome(1000); redditCookie(setCookies); } else { + if (popUp === false) { redirectHome(1000); redditCookie(setCookies, removeCookie); } else { // PopUp window setTimeout(() => { - redditCookie(setCookies); + redditCookie(setCookies, removeCookie); handleClose(); }, 1000); } diff --git a/src/components/Authentication/SignUp/SignUpUsername/signupUsernameServer.js b/src/components/Authentication/SignUp/SignUpUsername/signupUsernameServer.js index 328a69b9..cd95e85d 100644 --- a/src/components/Authentication/SignUp/SignUpUsername/signupUsernameServer.js +++ b/src/components/Authentication/SignUp/SignUpUsername/signupUsernameServer.js @@ -104,6 +104,7 @@ export const signUp = ( setDisabled, setRedirectCaption, setCookies, + removeCookie, popUp = false, handleClose = null, ) => { @@ -155,10 +156,13 @@ export const signUp = ( setRedirectCaption(true); // Add Reddit Cookie - if (popUp === false) { redirectHome(1000); redditCookie(setCookies); } else { + if (popUp === false) { + redirectHome(1000); + redditCookie(setCookies, removeCookie); + } else { // PopUp window setTimeout(() => { - redditCookie(setCookies); + redditCookie(setCookies, removeCookie); handleClose(); }, 1000); } diff --git a/src/components/Authentication/ThirdParty/ThirdPartyButton/ThirdPartyButton.test.jsx b/src/components/Authentication/ThirdParty/ThirdPartyButton/ThirdPartyButton.test.jsx new file mode 100644 index 00000000..eb232504 --- /dev/null +++ b/src/components/Authentication/ThirdParty/ThirdPartyButton/ThirdPartyButton.test.jsx @@ -0,0 +1,9 @@ +import renderer from 'react-test-renderer'; +import '@testing-library/jest-dom'; +import ThirdPartyButton from './ThirdPartyButton'; + +// test snapshot +test('ThirdPartyButton-test-snapshot', async () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/Authentication/ThirdParty/ThirdPartyButton/__snapshots__/ThirdPartyButton.test.jsx.snap b/src/components/Authentication/ThirdParty/ThirdPartyButton/__snapshots__/ThirdPartyButton.test.jsx.snap new file mode 100644 index 00000000..7d4260b7 --- /dev/null +++ b/src/components/Authentication/ThirdParty/ThirdPartyButton/__snapshots__/ThirdPartyButton.test.jsx.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ThirdPartyButton-test-snapshot 1`] = ` + +`; diff --git a/src/components/Authentication/authenticationServer.js b/src/components/Authentication/authenticationServer.js index b6fafb5b..f6bc08ff 100644 --- a/src/components/Authentication/authenticationServer.js +++ b/src/components/Authentication/authenticationServer.js @@ -28,16 +28,19 @@ export const removeRedditCookie = (removeCookie) => { */ export const redditCookie = async (setCookie, removeCookie) => { await axios.get('/users/me/').then((response) => { + console.log('Me in RedditCookie Response', response); if (response.status === 200) { - // set cookie + console.log('Reddit Cokkie Added Again'); + // set cookie const date = new Date(); date.setDate(date.getDate() + 90); setCookie('redditUser', response.data.user, { path: '/', expires: date }); } // unauthorized(invalid JWT) =>Redirect to login page - }).catch(() => { + }).catch((e) => { // redirectLogin(20); console.log('In Valid jwt'); + console.log(e); // Remove Reddit Cokkie if avaliable before removeRedditCookie(removeCookie); }); diff --git a/src/components/CreatePost/CreatePostContainer/CreatePostContainer.test.jsx b/src/components/CreatePost/CreatePostContainer/CreatePostContainer.test.jsx index 3b2e199a..aca11d60 100644 --- a/src/components/CreatePost/CreatePostContainer/CreatePostContainer.test.jsx +++ b/src/components/CreatePost/CreatePostContainer/CreatePostContainer.test.jsx @@ -1,15 +1,17 @@ import renderer from 'react-test-renderer'; -import '@testing-library/jest-dom'; import CreatePostContainer from './CreatePostContainer'; import CommunitiesInCreatePostContextProvider from '../../../contexts/CommunitiesInCreatePostContext'; +import CreatePostSidebarContextProvider from '../../../contexts/CreatePostSidebarContext'; describe(CreatePostContainer, () => { it('CreatePostContainer renders correctly', () => { const tree = renderer .create( - - - , + + + + + , ) .toJSON(); expect(tree).toMatchSnapshot(); diff --git a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/DraggableMedia/DraggableMedia.jsx b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/DraggableMedia/DraggableMedia.jsx index 4ee13e16..afb9dbd8 100644 --- a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/DraggableMedia/DraggableMedia.jsx +++ b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/DraggableMedia/DraggableMedia.jsx @@ -4,7 +4,19 @@ import ClearRoundedIcon from '@mui/icons-material/ClearRounded'; import { DeleteButton, Droppable, MediaFileContainer, MediaScreenShot, } from './styles'; - +/** + * This component is Draggable Media + * + * @component DraggableMedia + * @property {function} handlePostMedia -Handle the change in post media. + * @property {function} mediaSwap -To handle swapping between media. + * @property {function} mediaDelete -To handle delete media. + * @property {function} setActiveMediaFile -To set active media file. + * @property {Media} media -The object of media. + * @property {Number} activeMediaFile -The id of the active media file. + * @property {Number} id -The id of Draggable Media. + * @returns {React.Component} DraggableMedia + */ function DraggableMedia(props) { const { media, id, mediaSwap, activeMediaFile, setActiveMediaFile, mediaDelete, diff --git a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/DraggableMedia/DraggableMedia.test.jsx b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/DraggableMedia/DraggableMedia.test.jsx new file mode 100644 index 00000000..6990ab44 --- /dev/null +++ b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/DraggableMedia/DraggableMedia.test.jsx @@ -0,0 +1,33 @@ +import ShallowRenderer from 'react-test-renderer/shallow'; +import { HTML5Backend } from 'react-dnd-html5-backend'; +import { DndProvider } from 'react-dnd'; +import DraggableMedia from './DraggableMedia'; + +describe(DraggableMedia, () => { + // jest.mock('react-dnd', () => ({ + // ...jest.requireActual('react-dnd'), // use actual for all non-hook parts + // useDrag: (p) => ([{ isDragging: p }, 'drag']), + // useDrop: (x) => ([{ isOver: x }, 'drop']), + // })); + it('DraggableMedia renders correctly', () => { + const renderer = new ShallowRenderer(); + const tree = renderer + .render( + + (null)} + activeMediaFile={0} + setActiveMediaFile={() => (null)} + mediaDelete={() => (null)} + /> + , + ); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/DraggableMedia/__snapshots__/DraggableMedia.test.jsx.snap b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/DraggableMedia/__snapshots__/DraggableMedia.test.jsx.snap new file mode 100644 index 00000000..92aee626 --- /dev/null +++ b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/DraggableMedia/__snapshots__/DraggableMedia.test.jsx.snap @@ -0,0 +1,145 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`DraggableMedia DraggableMedia renders correctly 1`] = ` + + + +`; diff --git a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostMedia.jsx b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostMedia.jsx index dcdd0c60..b4998323 100644 --- a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostMedia.jsx +++ b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostMedia.jsx @@ -9,6 +9,19 @@ import DraggableMedia from './DraggableMedia/DraggableMedia'; import PostMediaDetails from './PostMediaDetails/PostMediaDetails'; import PostVideo from './PostVideo/PostVideo'; +/** + * This component is post media + * + * @component PostMedia + * @property {function} handlePostMedia -Handle the change in post media. + * @property {function} setPostMedia -To set post media + * @property {function} setActiveMediaFile -To set active media file + * @property {Array} postMedia -Array of post media. + * @property {Number} activeMediaFile -The id of the active media file. + * @property {Number} availableType -The type of available suploads (images or vidoes). + * @returns {React.Component} PostMedia + */ + function PostMedia(props) { // props const { diff --git a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostMedia.test.jsx b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostMedia.test.jsx new file mode 100644 index 00000000..f3349562 --- /dev/null +++ b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostMedia.test.jsx @@ -0,0 +1,25 @@ +// import renderer from 'react-test-renderer'; +import { ThemeProvider } from '@mui/system'; +import ShallowRenderer from 'react-test-renderer/shallow'; +import PostMedia from './PostMedia'; +import theme from '../../../../../styles/theme'; + +const renderer = new ShallowRenderer(); +describe(PostMedia, () => { + const mockHandler = jest.fn(); + it('PostMedia renders correctly', () => { + const tree = renderer.render( + + + , + ); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostMediaDetails/PostMediaDetails.test.jsx b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostMediaDetails/PostMediaDetails.test.jsx new file mode 100644 index 00000000..3012fa29 --- /dev/null +++ b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostMediaDetails/PostMediaDetails.test.jsx @@ -0,0 +1,36 @@ +import ShallowRenderer from 'react-test-renderer/shallow'; +import { ThemeProvider } from '@mui/system'; +import { DndProvider } from 'react-dnd'; +import { HTML5Backend } from 'react-dnd-html5-backend'; +import PostMediaDetails from './PostMediaDetails'; +import theme from '../../../../../../styles/theme'; + +jest.mock('react-dnd', () => ({ + ...jest.requireActual('react-dnd'), // use actual for all non-hook parts + useDrag: (p) => ([{ isDragging: p }, 'drag']), + useDrop: (x) => ([{ isOver: x }, 'drop']), +})); +describe(PostMediaDetails, () => { + it('PostMediaDetails renders correctly', () => { + const renderer = new ShallowRenderer(); + const tree = renderer + .render( + + + (null)} + handlePostLinkChange={() => (null)} + /> + + , + ); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostMediaDetails/__snapshots__/PostMediaDetails.test.jsx.snap b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostMediaDetails/__snapshots__/PostMediaDetails.test.jsx.snap new file mode 100644 index 00000000..ce509e6b --- /dev/null +++ b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostMediaDetails/__snapshots__/PostMediaDetails.test.jsx.snap @@ -0,0 +1,343 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PostMediaDetails PostMediaDetails renders correctly 1`] = ` + + + + + + + +`; diff --git a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostVideo/PostVideo.jsx b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostVideo/PostVideo.jsx index 32b4273b..3e521186 100644 --- a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostVideo/PostVideo.jsx +++ b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostVideo/PostVideo.jsx @@ -1,7 +1,14 @@ import DeleteIcon from '@mui/icons-material/Delete'; import { Box } from '@mui/material'; import { CustomIconButton } from './styles'; - +/** + * This component is post video + * + * @component PostVideo + * @property {string} src -video source. + * @property {function} setPostMedia -To set post media + * @returns {React.Component} PostVideo + */ /* eslint-disable jsx-a11y/media-has-caption */ function PostVideo(props) { const { src, setPostMedia } = props; diff --git a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostVideo/PostVideo.test.jsx b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostVideo/PostVideo.test.jsx new file mode 100644 index 00000000..4f41fca0 --- /dev/null +++ b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostVideo/PostVideo.test.jsx @@ -0,0 +1,11 @@ +import renderer from 'react-test-renderer'; +import PostVideo from './PostVideo'; + +describe(PostVideo, () => { + it('PostVideo renders correctly', () => { + const tree = renderer + .create( arr} />) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostVideo/__snapshots__/PostVideo.test.jsx.snap b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostVideo/__snapshots__/PostVideo.test.jsx.snap new file mode 100644 index 00000000..5a131c8c --- /dev/null +++ b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/PostVideo/__snapshots__/PostVideo.test.jsx.snap @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PostVideo PostVideo renders correctly 1`] = ` +
+ + +
+`; diff --git a/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/__snapshots__/PostMedia.test.jsx.snap b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/__snapshots__/PostMedia.test.jsx.snap new file mode 100644 index 00000000..63b9d4ad --- /dev/null +++ b/src/components/CreatePost/CreatePostContainer/CreatePostForm/PostMedia/__snapshots__/PostMedia.test.jsx.snap @@ -0,0 +1,336 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PostMedia PostMedia renders correctly 1`] = ` + + + + + +`; diff --git a/src/components/CreatePost/CreatePostContainer/SharePostForm/SharePostForm.test.jsx b/src/components/CreatePost/CreatePostContainer/SharePostForm/SharePostForm.test.jsx index 94e07ef9..7a0761ff 100644 --- a/src/components/CreatePost/CreatePostContainer/SharePostForm/SharePostForm.test.jsx +++ b/src/components/CreatePost/CreatePostContainer/SharePostForm/SharePostForm.test.jsx @@ -2,7 +2,7 @@ import '@testing-library/jest-dom'; import ShallowRenderer from 'react-test-renderer/shallow'; import React from 'react'; import PostTypeContextProvider from '../../../../contexts/PostTypeContext'; -import CreatePostForm from './CreatePostForm'; +import SharePostForm from './SharePostForm'; let realUseContext; let useContextMock; @@ -21,7 +21,7 @@ test('CreatePostForm', () => { useContextMock.mockReturnValue([]); const element = new ShallowRenderer().render( - + , ); expect(element.props.children).not.toBeNull(); diff --git a/src/components/ErrorPageComponent/ErrorPageComponent.jsx b/src/components/ErrorPageComponent/ErrorPageComponent.jsx new file mode 100644 index 00000000..5c3ae349 --- /dev/null +++ b/src/components/ErrorPageComponent/ErrorPageComponent.jsx @@ -0,0 +1,22 @@ +// MUI Components +import { Box, Typography } from '@mui/material'; +import { HomePageLink } from './styles'; + +function ErrorPageComponent() { + return ( + + Page Not Found + 404 page not found + the page you requested does not exist + + Redirect to + {' '} + Home + {' '} + ๐Ÿ  + + + ); +} + +export default ErrorPageComponent; diff --git a/src/components/ErrorPageComponent/ErrorPageComponent.test.jsx b/src/components/ErrorPageComponent/ErrorPageComponent.test.jsx new file mode 100644 index 00000000..c76268c6 --- /dev/null +++ b/src/components/ErrorPageComponent/ErrorPageComponent.test.jsx @@ -0,0 +1,13 @@ +import '@testing-library/jest-dom'; +import renderer from 'react-test-renderer'; +import { BrowserRouter as Router } from 'react-router-dom'; +import ErrorPageComponent from './ErrorPageComponent'; +// test snapshot +test('test snapshot', async () => { + const tree = renderer.create( + + + , + ).toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/ErrorPageComponent/__snapshots__/ErrorPageComponent.test.jsx.snap b/src/components/ErrorPageComponent/__snapshots__/ErrorPageComponent.test.jsx.snap new file mode 100644 index 00000000..82b38dfb --- /dev/null +++ b/src/components/ErrorPageComponent/__snapshots__/ErrorPageComponent.test.jsx.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` +
+ Page Not Found +

+ 404 page not found +

+

+ the page you requested does not exist +

+

+ Redirect to + + + Home + + + ๐Ÿ  +

+
+`; diff --git a/src/components/ErrorPageComponent/styles.js b/src/components/ErrorPageComponent/styles.js new file mode 100644 index 00000000..7b203fc2 --- /dev/null +++ b/src/components/ErrorPageComponent/styles.js @@ -0,0 +1,15 @@ +import { styled } from '@mui/system'; + +import theme from '../../styles/theme/index'; + +// Link to Home Page +export const HomePageLink = styled('a')(() => ({ + color: theme.palette.primary.main, + textDecoration: 'none', + // fontSize: '12px', + // fontWeight: '500', + + '&:hover': { + textDecoration: 'underline', + }, +})); diff --git a/src/components/Explore/CommunitiesContainer/CommunitiesContainer.jsx b/src/components/Explore/CommunitiesContainer/CommunitiesContainer.jsx index 0a6bbf12..745a36e5 100644 --- a/src/components/Explore/CommunitiesContainer/CommunitiesContainer.jsx +++ b/src/components/Explore/CommunitiesContainer/CommunitiesContainer.jsx @@ -5,6 +5,13 @@ import Community from '../Community/Community'; import { StyledCommunitiesContainer } from './styles'; import { exploreCommunities } from './CommunitiesTabServer'; +/** + * communities and their header + * @component + * @property {string} title title of the communities + * @return {React.Component} - communities and their header + */ + function CommunitiesContainer(props) { const { title } = props; const [communities] = exploreCommunities(title); diff --git a/src/components/Explore/CommunitiesContainer/CommunitiesContainer.test.jsx b/src/components/Explore/CommunitiesContainer/CommunitiesContainer.test.jsx new file mode 100644 index 00000000..c7a974d8 --- /dev/null +++ b/src/components/Explore/CommunitiesContainer/CommunitiesContainer.test.jsx @@ -0,0 +1,12 @@ +import renderer from 'react-test-renderer'; +import CommunitiesContainer from './CommunitiesContainer'; +import HeaderSubtitleContextProvider from '../../../contexts/HeaderSubtitleContext'; + +test('test snapshot', async () => { + const tree = renderer.create( + + + , + ).toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/Explore/CommunitiesContainer/CommunitiesTabServer.js b/src/components/Explore/CommunitiesContainer/CommunitiesTabServer.js index 411a98b5..a9cdec70 100644 --- a/src/components/Explore/CommunitiesContainer/CommunitiesTabServer.js +++ b/src/components/Explore/CommunitiesContainer/CommunitiesTabServer.js @@ -1,6 +1,13 @@ import { useState, useEffect } from 'react'; import axios from '../../../services/instance'; +/** +* +* Function to perfom api request and fetch communities +* @param {string} name - title of explore page +* @returns {Array} array of communities +*/ + export const exploreCommunities = (name) => { const [data, setData] = useState([]); diff --git a/src/components/Explore/CommunitiesContainer/__snapshots__/CommunitiesContainer.test.jsx.snap b/src/components/Explore/CommunitiesContainer/__snapshots__/CommunitiesContainer.test.jsx.snap new file mode 100644 index 00000000..604652f6 --- /dev/null +++ b/src/components/Explore/CommunitiesContainer/__snapshots__/CommunitiesContainer.test.jsx.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` +
+
+

+ Communities related to + + sports +

+
+
+`; diff --git a/src/components/Explore/CommunitiesHeader/CommunitiesHeader.jsx b/src/components/Explore/CommunitiesHeader/CommunitiesHeader.jsx index 38b2ce88..bcf7b238 100644 --- a/src/components/Explore/CommunitiesHeader/CommunitiesHeader.jsx +++ b/src/components/Explore/CommunitiesHeader/CommunitiesHeader.jsx @@ -1,6 +1,13 @@ import { Typography } from '@mui/material'; import { StyledHeader } from './styles'; +/** + * header of the communities + * @component + * @property {string} explore the explore page header + * @return {React.Component} - header of the communities + */ + function CommunitiesHeader(props) { const { explore } = props; return ( diff --git a/src/components/Explore/CommunitiesHeader/CommunitiesHeader.test.jsx b/src/components/Explore/CommunitiesHeader/CommunitiesHeader.test.jsx new file mode 100644 index 00000000..f3caab29 --- /dev/null +++ b/src/components/Explore/CommunitiesHeader/CommunitiesHeader.test.jsx @@ -0,0 +1,7 @@ +import renderer from 'react-test-renderer'; +import CommunitiesHeader from './CommunitiesHeader'; + +test('test snapshot', async () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/Explore/CommunitiesHeader/__snapshots__/CommunitiesHeader.test.jsx.snap b/src/components/Explore/CommunitiesHeader/__snapshots__/CommunitiesHeader.test.jsx.snap new file mode 100644 index 00000000..29879bf0 --- /dev/null +++ b/src/components/Explore/CommunitiesHeader/__snapshots__/CommunitiesHeader.test.jsx.snap @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` +
+

+ Communities related to + +

+
+`; diff --git a/src/components/Explore/CommunitiesTab/CommunitiesTab.jsx b/src/components/Explore/CommunitiesTab/CommunitiesTab.jsx index bfe96145..37ba1047 100644 --- a/src/components/Explore/CommunitiesTab/CommunitiesTab.jsx +++ b/src/components/Explore/CommunitiesTab/CommunitiesTab.jsx @@ -4,9 +4,15 @@ import CommunitiesContainer from '../CommunitiesContainer/CommunitiesContainer'; import SimilarTopics from '../SimilarTopics/SimilarTopics'; import { CommunitiesTabContainer } from './styles'; +/** + * the whole page of communities + * @component + * @property {string} title the title of the communities section + * @return {React.Component} - communities page + */ + function CommunitiesTab(props) { const { title } = props; - return ( { + const tree = renderer.create( + + + , + ).toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/Explore/CommunitiesTab/__snapshots__/CommunitiesTab.test.jsx.snap b/src/components/Explore/CommunitiesTab/__snapshots__/CommunitiesTab.test.jsx.snap new file mode 100644 index 00000000..c6bafaa3 --- /dev/null +++ b/src/components/Explore/CommunitiesTab/__snapshots__/CommunitiesTab.test.jsx.snap @@ -0,0 +1,157 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` +
+
+
+

+ Communities related to + + sports +

+
+
+
+
+
+

+ SIMILAR TOPICS +

+
+ + + + + link1 + +
+
+ + + + + link2 + +
+
+ + + + + Meta + +
+
+ + + + + link + +
+
+
+ +
+
+`; diff --git a/src/components/Explore/Community/Community.jsx b/src/components/Explore/Community/Community.jsx index e9515b6a..d1739d8c 100644 --- a/src/components/Explore/Community/Community.jsx +++ b/src/components/Explore/Community/Community.jsx @@ -4,6 +4,16 @@ import { } from './styles'; import JoinButton from '../../JoinButton/JoinButton'; +/** + * community instance + * @component + * @property {string} communityName the name of the community + * @property {string} communityPicture the link of the community image + * @property {string} numOfMembers number of members of the community + * @property {string} description discription of the community + * @return {React.Component} - community component of explore page + */ + function Community(props) { const { communityName, communityPicture, numOfMembers, description, @@ -45,7 +55,7 @@ function Community(props) { - + diff --git a/src/components/Explore/Community/Community.test.jsx b/src/components/Explore/Community/Community.test.jsx new file mode 100644 index 00000000..60d7f9ab --- /dev/null +++ b/src/components/Explore/Community/Community.test.jsx @@ -0,0 +1,7 @@ +import renderer from 'react-test-renderer'; +import Community from './Community'; + +test('test snapshot', async () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/Explore/Community/__snapshots__/Community.test.jsx.snap b/src/components/Explore/Community/__snapshots__/Community.test.jsx.snap new file mode 100644 index 00000000..4ae36577 --- /dev/null +++ b/src/components/Explore/Community/__snapshots__/Community.test.jsx.snap @@ -0,0 +1,91 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` +
+
+
+ + + +
+
+

+ r/ +

+

+ members +

+

+ +

+
+ +
+
+
+`; diff --git a/src/components/Explore/ExploreHeader/ExploreHeader.jsx b/src/components/Explore/ExploreHeader/ExploreHeader.jsx index dfe9b70c..54601119 100644 --- a/src/components/Explore/ExploreHeader/ExploreHeader.jsx +++ b/src/components/Explore/ExploreHeader/ExploreHeader.jsx @@ -4,6 +4,13 @@ import { HeaderContainer, StyledLink } from './styles'; import NavButtons from '../NavButtons/NavButtons'; import { useHeaderSubtitleContext } from '../../../contexts/HeaderSubtitleContext'; +/** + * explore page header + * @component + * @property {string} headerSubtitle the header title of the explore page + * @return {React.Component} - explore page header component + */ + function ExploreHeader(props) { const { headerSubtitle, diff --git a/src/components/Explore/ExploreHeader/ExploreHeader.test.jsx b/src/components/Explore/ExploreHeader/ExploreHeader.test.jsx new file mode 100644 index 00000000..5ff6b1df --- /dev/null +++ b/src/components/Explore/ExploreHeader/ExploreHeader.test.jsx @@ -0,0 +1,12 @@ +import renderer from 'react-test-renderer'; +import ExploreHeader from './ExploreHeader'; +import HeaderSubtitleContextProvider from '../../../contexts/HeaderSubtitleContext'; + +test('test snapshot', async () => { + const tree = renderer.create( + + + , + ).toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/Explore/ExploreHeader/__snapshots__/ExploreHeader.test.jsx.snap b/src/components/Explore/ExploreHeader/__snapshots__/ExploreHeader.test.jsx.snap new file mode 100644 index 00000000..dff2a27a --- /dev/null +++ b/src/components/Explore/ExploreHeader/__snapshots__/ExploreHeader.test.jsx.snap @@ -0,0 +1,118 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` +
+
+

+ + 0 + +

+
+
+
+
+ + +
+
+
+ + +
+`; diff --git a/src/components/Explore/ExploreMainPage/ExploreMainPage.jsx b/src/components/Explore/ExploreMainPage/ExploreMainPage.jsx index ffd4aff8..79d90485 100644 --- a/src/components/Explore/ExploreMainPage/ExploreMainPage.jsx +++ b/src/components/Explore/ExploreMainPage/ExploreMainPage.jsx @@ -2,6 +2,13 @@ import HeaderSubtitleContextProvider from '../../../contexts/HeaderSubtitleConte import { ExpMainPage } from './styles'; import ExploreHeader from '../ExploreHeader/ExploreHeader'; +/** + * the explore main page + * @component + * @property {string} title the title of the explore main page + * @return {React.Component} - the explore main page + */ + function ExploreMainPage(props) { const { title } = props; return ( diff --git a/src/components/Explore/ExploreMainPage/ExploreMainPage.test.jsx b/src/components/Explore/ExploreMainPage/ExploreMainPage.test.jsx new file mode 100644 index 00000000..8cd1e2be --- /dev/null +++ b/src/components/Explore/ExploreMainPage/ExploreMainPage.test.jsx @@ -0,0 +1,7 @@ +import renderer from 'react-test-renderer'; +import ExploreMainPage from './ExploreMainPage'; + +test('test snapshot', async () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/Explore/ExploreMainPage/__snapshots__/ExploreMainPage.test.jsx.snap b/src/components/Explore/ExploreMainPage/__snapshots__/ExploreMainPage.test.jsx.snap new file mode 100644 index 00000000..8cdf34de --- /dev/null +++ b/src/components/Explore/ExploreMainPage/__snapshots__/ExploreMainPage.test.jsx.snap @@ -0,0 +1,122 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` +
+
+
+

+ + 0 + +

+
+
+
+
+ + +
+
+
+ + +
+
+`; diff --git a/src/components/Explore/NavButtons/NavButtons.jsx b/src/components/Explore/NavButtons/NavButtons.jsx index 9b7adbf5..b89ba592 100644 --- a/src/components/Explore/NavButtons/NavButtons.jsx +++ b/src/components/Explore/NavButtons/NavButtons.jsx @@ -6,6 +6,13 @@ import TabPanel from '@mui/lab/TabPanel'; import { StyledTabs } from './styles'; import CommunitiesTab from '../CommunitiesTab/CommunitiesTab'; +/** + * navigation button for explore page between communities and posts + * @component + * @property {string} title the title of the communities + * @return {React.Component} - navigation buttons component + */ + export default function NavButtons(props) { const { title } = props; const [value, setValue] = React.useState('1'); diff --git a/src/components/Explore/NavButtons/NavButtons.test.jsx b/src/components/Explore/NavButtons/NavButtons.test.jsx new file mode 100644 index 00000000..69eeb200 --- /dev/null +++ b/src/components/Explore/NavButtons/NavButtons.test.jsx @@ -0,0 +1,7 @@ +import renderer from 'react-test-renderer'; +import NavButtons from './NavButtons'; + +test('test snapshot', async () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/Explore/NavButtons/__snapshots__/NavButtons.test.jsx.snap b/src/components/Explore/NavButtons/__snapshots__/NavButtons.test.jsx.snap new file mode 100644 index 00000000..2ea1a21b --- /dev/null +++ b/src/components/Explore/NavButtons/__snapshots__/NavButtons.test.jsx.snap @@ -0,0 +1,100 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` +
+
+
+
+ + +
+
+
+ + +`; diff --git a/src/components/Explore/SimilarTopics/SimilarTopics.jsx b/src/components/Explore/SimilarTopics/SimilarTopics.jsx index 7d484597..28a8efc9 100644 --- a/src/components/Explore/SimilarTopics/SimilarTopics.jsx +++ b/src/components/Explore/SimilarTopics/SimilarTopics.jsx @@ -6,6 +6,12 @@ import { const arr = ['link1', 'link2', 'Meta', 'link']; +/** + * similar topics of the explore page + * @component + * @return {React.Component} - similar topics component + */ + function SimilarTopics() { return ( diff --git a/src/components/Explore/SimilarTopics/SimilarTopics.test.jsx b/src/components/Explore/SimilarTopics/SimilarTopics.test.jsx new file mode 100644 index 00000000..a6df6b87 --- /dev/null +++ b/src/components/Explore/SimilarTopics/SimilarTopics.test.jsx @@ -0,0 +1,7 @@ +import renderer from 'react-test-renderer'; +import SimilarTopics from './SimilarTopics'; + +test('test snapshot', async () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/Explore/SimilarTopics/__snapshots__/SimilarTopics.test.jsx.snap b/src/components/Explore/SimilarTopics/__snapshots__/SimilarTopics.test.jsx.snap new file mode 100644 index 00000000..7307ba57 --- /dev/null +++ b/src/components/Explore/SimilarTopics/__snapshots__/SimilarTopics.test.jsx.snap @@ -0,0 +1,109 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` +
+
+

+ SIMILAR TOPICS +

+
+ + + + + link1 + +
+
+ + + + + link2 + +
+
+ + + + + Meta + +
+
+ + + + + link + +
+
+
+`; diff --git a/src/components/HomePage/HomePageContainer/Communities/Communities.test.jsx b/src/components/HomePage/HomePageContainer/Communities/Communities.test.jsx index 261aa0eb..2f17cc2d 100644 --- a/src/components/HomePage/HomePageContainer/Communities/Communities.test.jsx +++ b/src/components/HomePage/HomePageContainer/Communities/Communities.test.jsx @@ -7,10 +7,7 @@ import Communities from './Communities'; describe(Communities, () => { test('Communities is in the document', () => { - const communities = { - communitiesTitle: 'communities near you', - communitiesList: [], - }; + const communities = []; render( @@ -21,16 +18,13 @@ describe(Communities, () => { }); test('Communities props works correctly', () => { - const communities = { - communitiesTitle: 'communities near you', - communitiesList: [], - }; + const communities = []; render( , ); const communitiesTitle = screen.getByTestId('communities title'); - expect(communitiesTitle.textContent).toEqual(communities.communitiesTitle); + expect(communitiesTitle.textContent).toEqual('communities near you'); }); }); diff --git a/src/components/HomePage/HomePageContainer/Communities/CommunityList/CommunityItem/CommunityItem.test.jsx b/src/components/HomePage/HomePageContainer/Communities/CommunityList/CommunityItem/CommunityItem.test.jsx index 086d458c..2a3d9272 100644 --- a/src/components/HomePage/HomePageContainer/Communities/CommunityList/CommunityItem/CommunityItem.test.jsx +++ b/src/components/HomePage/HomePageContainer/Communities/CommunityList/CommunityItem/CommunityItem.test.jsx @@ -2,6 +2,11 @@ import { render, screen } from '@testing-library/react'; import '@testing-library/jest-dom'; import CommunityItem from './CommunityItem'; +const mockedUsedNavigate = jest.fn(); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => mockedUsedNavigate, +})); describe(CommunityItem, () => { test('Community Item is in the document', () => { render(); diff --git a/src/components/HomePage/HomePageContainer/HomePageContainer.jsx b/src/components/HomePage/HomePageContainer/HomePageContainer.jsx index 6ae6ed6b..ae3af380 100644 --- a/src/components/HomePage/HomePageContainer/HomePageContainer.jsx +++ b/src/components/HomePage/HomePageContainer/HomePageContainer.jsx @@ -48,7 +48,7 @@ function HomePageContainer() { {match && ( - {!communitiesError ? (communities && ) : 'error in fetching commmunities'} + {cookies.redditUser && (!communitiesError ? (communities && ) : 'error in fetching commmunities')} { - it('HomePageContainer renders correctly', () => { + it('PopularContainer renders correctly', () => { const tree = renderer .create( - - - - - + + + + + + + + + + + + + , , + ) .toJSON(); expect(tree).toMatchSnapshot(); diff --git a/src/components/HomePage/HomePageContainer/PostList/PostList.jsx b/src/components/HomePage/HomePageContainer/PostList/PostList.jsx index bf460764..65f4082c 100644 --- a/src/components/HomePage/HomePageContainer/PostList/PostList.jsx +++ b/src/components/HomePage/HomePageContainer/PostList/PostList.jsx @@ -7,6 +7,7 @@ import Post from '../../../Post/Post'; * * @component PostList * @property {Array.} posts -post objects fetched + * @property {boolean} subredit -Whether the call of post list from subreddit or not. * @returns {React.Component} List of all posts */ diff --git a/src/components/HomePage/HomePageContainer/PostList/PostList.test.jsx b/src/components/HomePage/HomePageContainer/PostList/PostList.test.jsx index 5479a60a..4f2e65d6 100644 --- a/src/components/HomePage/HomePageContainer/PostList/PostList.test.jsx +++ b/src/components/HomePage/HomePageContainer/PostList/PostList.test.jsx @@ -5,45 +5,80 @@ import { ThemeProvider } from '@mui/system'; import { MemoryRouter as Router } from 'react-router-dom'; import theme from '../../../../styles/theme'; import PostList from './PostList'; +import ListingContextProvider from '../../../../contexts/ListingContext'; +import PostTypeContextProvider from '../../../../contexts/PostTypeContext'; +import HiddenPostsContextProvider from '../../../../contexts/HiddenPostsContext'; +import EditPostContextProvider from '../../../../contexts/EditPostContext'; +import CreatePostSidebarContextProvider from '../../../../contexts/CreatePostSidebarContext'; describe(PostList, () => { - it('Reactions renders correctly', () => { - const testCase = [{ - commentCount: - 12, - author: - 'righteous_boldness07', - flairBackgroundColor: - '#0079D3', - flairColor: - '#000', - flairText: - 'sports/r/all', - id: - 0, - image: - 'https://styles.redditmedia.com/t5_3ptyd/styles/communityIcon_p18jqwszxcv51.png', - kind: - 'image', - popularity: - 'Popular videos', - sr: - 'toptalent', - title: - 'In 1991 Michael Jordan shot a free throw with his eyes closed while playing the Denver Nuggets.', - url: - 'https://external-preview.redd.it/IRAK4IuafQCZdIC_OnB0X2ASJrSSRjqL7Vtnx3jt6mc.jpg?width=640&crop=smart&auto=webp&s=1db6de95af4fecf325ed1f06771b9a6eb947ac8e', - votes: - 245, - }]; + it('PostList renders correctly', () => { + const testCase = [ + JSON.parse(`{ + "_id": "63a039107e9602e5da79ac42", + "ownerType": "User", + "replies": [ + "63a03c427e9602e5da79ac8b", + "63a03c457e9602e5da79ac97", + "63a03c4a7e9602e5da79aca3", + "63a03c4c7e9602e5da79acaf" + ], + "title": "new Post @ 12:12", + "kind": "self", + "text": "

Edited Post

", + "url": "", + "images": [], + "createdAt": "2022-12-19T10:06:05.781Z", + "locked": false, + "isDeleted": false, + "sendReplies": true, + "nsfw": false, + "spoiler": false, + "votes": 0, + "views": 0, + "commentCount": 4, + "shareCount": 0, + "suggestedSort": "new", + "scheduled": false, + "modState": "unmoderated", + "spamCount": 0, + "spammedBy": [], + "sortOnHot": 835722182890.5, + "sortOnBest": 668577746312.4, + "__v": 0, + "owner": { + "_id": "639f824cd9f48a8d75a21aa4", + "name": "Basma", + "icon": "https://api.nonlegit.click/users/default.png" + }, + "author": { + "_id": "639f824cd9f48a8d75a21aa4", + "name": "Basma" + }, + "isSaved": false, + "postVoteStatus": 0, + "isSpam": false + }`), + ]; const tree = renderer .create( - - - + + + + + + + + + + + + + + , ) diff --git a/src/components/HomePage/HomePageContainer/PostList/__snapshots__/PostList.test.jsx.snap b/src/components/HomePage/HomePageContainer/PostList/__snapshots__/PostList.test.jsx.snap index 6af94444..9f7f9d24 100644 --- a/src/components/HomePage/HomePageContainer/PostList/__snapshots__/PostList.test.jsx.snap +++ b/src/components/HomePage/HomePageContainer/PostList/__snapshots__/PostList.test.jsx.snap @@ -1,363 +1,215 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PostList Reactions renders correctly 1`] = ` +exports[`PostList PostList renders correctly 1`] = ` +
+ - - - - - Share - -
- -
    +
+
+ +
+ 0 +
+ +
+
-
-
+ 4 + + comments + +
-
+ + Share +
-
-
-
+
    - - report - -
+
+ + + +
+
+ + Save + +
+
+
+
+
+ + + +
+
+ + edit post + +
+
+
+
+
+ + + +
+
+ + hide + +
+
+
+
+
+ + + +
+
+ + delete + +
+
+
+
+
+ + + +
+
+ + report + +
+
+
- +
diff --git a/src/components/HomePage/HomePageContainer/__snapshots__/HomePageContainer.test.jsx.snap b/src/components/HomePage/HomePageContainer/__snapshots__/HomePageContainer.test.jsx.snap index 45cdf2f1..70fcf017 100644 --- a/src/components/HomePage/HomePageContainer/__snapshots__/HomePageContainer.test.jsx.snap +++ b/src/components/HomePage/HomePageContainer/__snapshots__/HomePageContainer.test.jsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`HomePageContainer HomePageContainer renders correctly 1`] = ` +exports[`HomePageContainer PopularContainer renders correctly 1`] = ` Array [
{ + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/MainNavBar/Navbar/Logo/LogoIcon.test.jsx b/src/components/MainNavBar/Navbar/Logo/LogoIcon.test.jsx index 67527004..ae0b7b9c 100644 --- a/src/components/MainNavBar/Navbar/Logo/LogoIcon.test.jsx +++ b/src/components/MainNavBar/Navbar/Logo/LogoIcon.test.jsx @@ -3,12 +3,11 @@ import { BrowserRouter as Router } from 'react-router-dom'; import LogoIcon from './logoIcon'; import Navbar from '../Navbar'; -global.matchMedia = global.matchMedia || function () { - return { - addListener: jest.fn(), - removeListener: jest.fn(), - }; -}; +const mockedUsedMessaging = jest.fn(); +jest.mock('firebase/messaging', () => ({ + ...jest.requireActual('firebase/messaging'), + getMessaging: () => mockedUsedMessaging, +})); test('test snapshot', async () => { const tree = renderer.create().toJSON(); expect(tree).toMatchSnapshot(); diff --git a/src/components/MainNavBar/Navbar/NavIcons/NavIcons.jsx b/src/components/MainNavBar/Navbar/NavIcons/NavIcons.jsx index ef9aed5c..986281d8 100644 --- a/src/components/MainNavBar/Navbar/NavIcons/NavIcons.jsx +++ b/src/components/MainNavBar/Navbar/NavIcons/NavIcons.jsx @@ -11,6 +11,7 @@ import { Link, useNavigate } from 'react-router-dom'; import { useState, useEffect } from 'react'; import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined'; import BeenhereOutlinedIcon from '@mui/icons-material/BeenhereOutlined'; +import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline'; import { onForegroundNottification } from '../../../../lib/firebase'; import { StyledTooltip, NotificationButton, NotificationContent, NotificationContanier, @@ -35,7 +36,8 @@ function NavIcons() { const [dataToday, dataEarlier] = notificationsFetch(); // anchor element const [anchorEl, setAnchorEl] = useState(null); - const [unread, setUnread] = useState(1); + const [unread, setUnread] = useState(0); + const [message, setMessage] = useState(false); const [anchorElWindow, setAnchorElWindow] = useState(null); const openWindow = Boolean(anchorElWindow); const open = Boolean(anchorEl); @@ -53,7 +55,13 @@ function NavIcons() { onForegroundNottification() .then((payload) => { const { data: { val } } = payload; - setToday((oldArray) => [JSON.parse(val), ...oldArray]); + const value = JSON.parse(val); + if (value.type === 'follow' || value.type === 'commentReply' || value.type === 'userMention' || value.type === 'firstPostUpVote' || value.type === 'firstCommentUpVote') { setToday((oldArray) => [value, ...oldArray]); } else { + setMessage(true); + } + if (value.type === 'postReply') { + setToday((oldArray) => [value, ...oldArray]); + } setUnread(unread + 1); }) .catch((err) => console.log('An error occured while retrieving foreground message. ', err)); @@ -123,7 +131,9 @@ function NavIcons() { Notifications - + + { (message) && } + {' '} Messages diff --git a/src/components/MainNavBar/Navbar/Navbar.jsx b/src/components/MainNavBar/Navbar/Navbar.jsx index 08791f22..c5bfb2a3 100644 --- a/src/components/MainNavBar/Navbar/Navbar.jsx +++ b/src/components/MainNavBar/Navbar/Navbar.jsx @@ -21,6 +21,7 @@ function Navbar() { && window.location.pathname !== '/register' && window.location.pathname !== '/username' && pathArray[1] !== 'resetpassword' + && pathArray[1] !== 'verification' && ( diff --git a/src/components/MainNavBar/Navbar/UserList/UserList.test.jsx b/src/components/MainNavBar/Navbar/UserList/UserList.test.jsx index 402dcd80..add3dc21 100644 --- a/src/components/MainNavBar/Navbar/UserList/UserList.test.jsx +++ b/src/components/MainNavBar/Navbar/UserList/UserList.test.jsx @@ -1,6 +1,12 @@ import renderer from 'react-test-renderer'; import UserList from './UserList'; +const mockedUsedNavigate = jest.fn(); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => mockedUsedNavigate, +})); + test('test snapshot', async () => { const tree = renderer.create().toJSON(); expect(tree).toMatchSnapshot(); diff --git a/src/components/MainNavBar/Navbar/UserList/server.js b/src/components/MainNavBar/Navbar/UserList/server.js index ec67f0e9..4fb54686 100644 --- a/src/components/MainNavBar/Navbar/UserList/server.js +++ b/src/components/MainNavBar/Navbar/UserList/server.js @@ -8,10 +8,11 @@ import { removeRedditCookie } from '../../../Authentication/authenticationServer export const logOut = (removeCookie) => { console.log('Logout clicked'); axios.post('/users/logout').then((response) => { + console.log('logout Response', response); // jwt Cookie is sucessfully removed if (response.status === 200 || response.status === 201) { // remove Reddit Cookie - + console.log('Removed'); removeRedditCookie(removeCookie); if (localStorage.getItem('RedditHistory')) { localStorage.removeItem('RedditHistory'); diff --git a/src/components/MainNavBar/Search/Search.test.jsx b/src/components/MainNavBar/Search/Search.test.jsx index 2f996039..1185735d 100644 --- a/src/components/MainNavBar/Search/Search.test.jsx +++ b/src/components/MainNavBar/Search/Search.test.jsx @@ -1,7 +1,14 @@ import renderer from 'react-test-renderer'; +import { BrowserRouter as Router } from 'react-router-dom'; import SearchField from './Search'; +const mockedUsedNavigate = jest.fn(); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => mockedUsedNavigate, +})); + test('test snapshot', async () => { - const tree = renderer.create().toJSON(); + const tree = renderer.create().toJSON(); expect(tree).toMatchSnapshot(); }); diff --git a/src/components/MainNavBar/Search/__snapshots__/Search.test.jsx.snap b/src/components/MainNavBar/Search/__snapshots__/Search.test.jsx.snap index 9d41a7fd..bdb3ccb2 100644 --- a/src/components/MainNavBar/Search/__snapshots__/Search.test.jsx.snap +++ b/src/components/MainNavBar/Search/__snapshots__/Search.test.jsx.snap @@ -15,18 +15,55 @@ exports[`test snapshot 1`] = ` d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" /> +
+ + + + +
diff --git a/src/components/MainNavBar/SignNavbar/ForgetPassPopUp/ForgetPass.jsx b/src/components/MainNavBar/SignNavbar/ForgetPassPopUp/ForgetPass.jsx index 4da807f7..a4576dcd 100644 --- a/src/components/MainNavBar/SignNavbar/ForgetPassPopUp/ForgetPass.jsx +++ b/src/components/MainNavBar/SignNavbar/ForgetPassPopUp/ForgetPass.jsx @@ -4,7 +4,6 @@ import * as React from 'react'; import CloseIcon from '@mui/icons-material/Close'; import { useEffect, useState } from 'react'; import { useCookies } from 'react-cookie'; -import Cookies from 'js-cookie'; import { ForgetPassContext } from '../SignNavbar'; // import StyledDialog from '../styles'; import { @@ -18,8 +17,8 @@ import { redditCookie, checkEmail } from '../../../Authentication/authentication import theme, { fonts } from '../../../../styles/theme'; import { StyledDialog } from '../styles'; - -const { REACT_APP_ENV } = process.env; +// ultis +import { redirectLogin } from '../../../../utils/Redirect'; /** * ForgetPassword popUp @@ -40,7 +39,7 @@ function ForgetPassword() { }); // cookies - const [cookies, setCookies] = useCookies(['redditUser']); + const [cookies, setCookies, removeCookie] = useCookies(['redditUser']); const { openForgotpass, handleClose, @@ -51,15 +50,26 @@ function ForgetPassword() { // useEffect useEffect(() => { - // Check on Cookies - // developememt - if (REACT_APP_ENV !== 'development' && Cookies.get('jwt')) { + // Check on Cookies + // developememt + /// Ask if this user already loggied in the back + // Remove Old Cookie :)==>Of course he is signed out + redditCookie(setCookies, removeCookie); + // if logged in in the back end + if (cookies.redditUser !== undefined) { // production - // Redirect to loading page + // Update Cookie + // redditCookie(setCookies); // check on Reddit cookie - if (cookies.redditUser === undefined) { - redditCookie(setCookies); - } + // if (cookies.redditUser === undefined) { + // redditCookie(setCookies); + // } + // Redirect to loading page + console.log('Remember me is set to true'); + redirectLogin(2); + } else { + // No Cookie by Back End + console.log('Remember me is set to false'); } }, []); diff --git a/src/components/MainNavBar/SignNavbar/ForgetPassPopUp/__snapshots__/ForgetPass.test.jsx.snap b/src/components/MainNavBar/SignNavbar/ForgetPassPopUp/__snapshots__/ForgetPass.test.jsx.snap index a5ada17a..ec9cf08e 100644 --- a/src/components/MainNavBar/SignNavbar/ForgetPassPopUp/__snapshots__/ForgetPass.test.jsx.snap +++ b/src/components/MainNavBar/SignNavbar/ForgetPassPopUp/__snapshots__/ForgetPass.test.jsx.snap @@ -157,18 +157,55 @@ Array [ d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" /> +
+ + + + +
diff --git a/src/components/MainNavBar/SignNavbar/ForgetUserNamePopUp/ForgetUser.jsx b/src/components/MainNavBar/SignNavbar/ForgetUserNamePopUp/ForgetUser.jsx index 3ae9d173..80d0c193 100644 --- a/src/components/MainNavBar/SignNavbar/ForgetUserNamePopUp/ForgetUser.jsx +++ b/src/components/MainNavBar/SignNavbar/ForgetUserNamePopUp/ForgetUser.jsx @@ -4,7 +4,7 @@ import * as React from 'react'; import CloseIcon from '@mui/icons-material/Close'; import { useEffect, useState } from 'react'; import { useCookies } from 'react-cookie'; -import Cookies from 'js-cookie'; + import { ForgetUserContext } from '../SignNavbar'; import { StyledDialog } from '../styles'; import { StyledLink } from '../ูAuthentication/styles'; @@ -15,8 +15,9 @@ import { recoverUsername } from './server'; import { redditCookie } from '../../../Authentication/authenticationServer'; import theme, { fonts } from '../../../../styles/theme'; -// environment variables -const { REACT_APP_ENV } = process.env; + +// // environment variables +// const { REACT_APP_ENV } = process.env; /** * ForgetUsername popUp * @component @@ -34,7 +35,8 @@ function ForgetUsername() { const [disabled, setDisabled] = useState(false); const [redirectCaption, setRedirectCaption] = useState(false); // cookies - const [cookies, setCookies] = useCookies(['redditUser']); + // eslint-disable-next-line no-unused-vars + const [cookies, setCookies, removeCookie] = useCookies(['redditUser']); const { openForgotUser, @@ -47,14 +49,26 @@ function ForgetUsername() { useEffect(() => { // Check on Cookies // developememt - if (REACT_APP_ENV !== 'development' && Cookies.get('jwt')) { - // production - // Redirect to loading page - // check on Reddit cookie - if (cookies.redditUser === undefined) { - redditCookie(setCookies); - } - } + /// Ask if this user already loggied in the back + // Remove Old Cookie :)==>Of course he is signed out + redditCookie(setCookies, removeCookie); + // if logged in in the back end + // if (cookies.redditUser !== undefined) { + // // production + // // Update Cookie + // // redditCookie(setCookies); + // // check on Reddit cookie + // // if (cookies.redditUser === undefined) { + // // redditCookie(setCookies); + // // } + // // Redirect to loading page + // console.log('Remember me is set to true'); + // handleClose(); + // redirectHome(100); + // } else { + // // No Cookie by Back End + // console.log('Remember me is set to false'); + // } }, []); const caption = ( diff --git a/src/components/MainNavBar/SignNavbar/ForgetUserNamePopUp/__snapshots__/ForgetUser.test.jsx.snap b/src/components/MainNavBar/SignNavbar/ForgetUserNamePopUp/__snapshots__/ForgetUser.test.jsx.snap index 1dd1d910..1b933bdf 100644 --- a/src/components/MainNavBar/SignNavbar/ForgetUserNamePopUp/__snapshots__/ForgetUser.test.jsx.snap +++ b/src/components/MainNavBar/SignNavbar/ForgetUserNamePopUp/__snapshots__/ForgetUser.test.jsx.snap @@ -157,18 +157,55 @@ Array [ d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" /> +
+ + + + +
diff --git a/src/components/MainNavBar/SignNavbar/HomeList/HomeList.test.jsx b/src/components/MainNavBar/SignNavbar/HomeList/HomeList.test.jsx index 067f312d..c29cc30c 100644 --- a/src/components/MainNavBar/SignNavbar/HomeList/HomeList.test.jsx +++ b/src/components/MainNavBar/SignNavbar/HomeList/HomeList.test.jsx @@ -1,6 +1,12 @@ import renderer from 'react-test-renderer'; import HomeList from './HomeList'; +const mockedUsedNavigate = jest.fn(); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => mockedUsedNavigate, +})); + test('test snapshot', async () => { const tree = renderer.create().toJSON(); expect(tree).toMatchSnapshot(); diff --git a/src/components/MainNavBar/SignNavbar/LogInPopUp/__snapshots__/LogIn.test.jsx.snap b/src/components/MainNavBar/SignNavbar/LogInPopUp/__snapshots__/LogIn.test.jsx.snap index 1dd1d910..1b933bdf 100644 --- a/src/components/MainNavBar/SignNavbar/LogInPopUp/__snapshots__/LogIn.test.jsx.snap +++ b/src/components/MainNavBar/SignNavbar/LogInPopUp/__snapshots__/LogIn.test.jsx.snap @@ -157,18 +157,55 @@ Array [ d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" /> +
+ + + + +
diff --git a/src/components/MainNavBar/SignNavbar/SignNavbar.jsx b/src/components/MainNavBar/SignNavbar/SignNavbar.jsx index 3e770ad8..23022106 100644 --- a/src/components/MainNavBar/SignNavbar/SignNavbar.jsx +++ b/src/components/MainNavBar/SignNavbar/SignNavbar.jsx @@ -89,6 +89,7 @@ function SignNavbar() { && window.location.pathname !== '/register' && window.location.pathname !== '/username' && pathArray[1] !== 'resetpassword' + && pathArray[1] !== 'verification' && ( <> diff --git a/src/components/MainNavBar/SignNavbar/SignUpPopUp/SignUpPopUp.jsx b/src/components/MainNavBar/SignNavbar/SignUpPopUp/SignUpPopUp.jsx index 659e458f..9613530b 100644 --- a/src/components/MainNavBar/SignNavbar/SignUpPopUp/SignUpPopUp.jsx +++ b/src/components/MainNavBar/SignNavbar/SignUpPopUp/SignUpPopUp.jsx @@ -24,10 +24,10 @@ function SignUpPopUp() { // cookies // eslint-disable-next-line no-unused-vars - const [cookies, setCookies] = useCookies(['redditUser']); + const [cookies, setCookies, removeCookie] = useCookies(['redditUser']); const signUpView = userNamePage - ? + ? : ; return ( diff --git a/src/components/MainNavBar/SignNavbar/SignUpPopUp/SignUpPopUpUserName/SignUpPopUpUserName.jsx b/src/components/MainNavBar/SignNavbar/SignUpPopUp/SignUpPopUpUserName/SignUpPopUpUserName.jsx index 309c6604..bdcd24fa 100644 --- a/src/components/MainNavBar/SignNavbar/SignUpPopUp/SignUpPopUpUserName/SignUpPopUpUserName.jsx +++ b/src/components/MainNavBar/SignNavbar/SignUpPopUp/SignUpPopUpUserName/SignUpPopUpUserName.jsx @@ -39,7 +39,7 @@ const { REACT_APP_SITEKEY } = process.env; * @returns {React.Component} - Main Body of SignUp UseerName PopUp */ function SignUpPopUpUserName({ - setUserNamePage, email, userName, setUserName, password, setPassword, setCookies, + setUserNamePage, email, userName, setUserName, password, setPassword, setCookies, removeCookie, }) { // states const [defaultUserNameValue, setdefaultUserNameValue] = useState(userName?.input); @@ -106,7 +106,7 @@ function SignUpPopUpUserName({ // console.log(userName); checkUserNameSignUp(userName?.input, setUserName); checkPassword(password?.input, setPassword, password); - signUp(email, userName, setUserName, password, setPassword, verified, setLoading, setButtonText, setDisabled, setRedirectCaption, setCookies, true, handleClose); + signUp(email, userName, setUserName, password, setPassword, verified, setLoading, setButtonText, setDisabled, setRedirectCaption, setCookies, removeCookie, true, handleClose); }; return ( diff --git a/src/components/MainNavBar/SignNavbar/SignUpPopUp/__snapshots__/SignUp.test.jsx.snap b/src/components/MainNavBar/SignNavbar/SignUpPopUp/__snapshots__/SignUp.test.jsx.snap index 1dd1d910..1b933bdf 100644 --- a/src/components/MainNavBar/SignNavbar/SignUpPopUp/__snapshots__/SignUp.test.jsx.snap +++ b/src/components/MainNavBar/SignNavbar/SignUpPopUp/__snapshots__/SignUp.test.jsx.snap @@ -157,18 +157,55 @@ Array [ d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" /> +
+ + + + +
diff --git a/src/components/MainNavBar/SignNavbar/__snapshots__/SignNavbar.test.jsx.snap b/src/components/MainNavBar/SignNavbar/__snapshots__/SignNavbar.test.jsx.snap index 1dd1d910..1b933bdf 100644 --- a/src/components/MainNavBar/SignNavbar/__snapshots__/SignNavbar.test.jsx.snap +++ b/src/components/MainNavBar/SignNavbar/__snapshots__/SignNavbar.test.jsx.snap @@ -157,18 +157,55 @@ Array [ d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" /> +
+ + + + +
diff --git "a/src/components/MainNavBar/SignNavbar/\331\220Authentication/FirstParty/FirstParty.jsx" "b/src/components/MainNavBar/SignNavbar/\331\220Authentication/FirstParty/FirstParty.jsx" index 16041094..af03d1ef 100644 --- "a/src/components/MainNavBar/SignNavbar/\331\220Authentication/FirstParty/FirstParty.jsx" +++ "b/src/components/MainNavBar/SignNavbar/\331\220Authentication/FirstParty/FirstParty.jsx" @@ -33,7 +33,7 @@ function FirstParty({ handleClose }) { // useCookies // eslint-disable-next-line no-unused-vars - const [cookies, setCookies] = useCookies(['redditUser']); + const [cookies, setCookies, removeCookie] = useCookies(['redditUser']); return ( { console.log(entity); if (entity?.ownerType === 'Subreddit' && communities?.filter((element) => element.fixedName === entity?.owner.name).length > 0) { diff --git a/src/components/MainProfile/Comments/Comments.test.jsx b/src/components/MainProfile/Comments/Comments.test.jsx new file mode 100644 index 00000000..a7fa634e --- /dev/null +++ b/src/components/MainProfile/Comments/Comments.test.jsx @@ -0,0 +1,19 @@ +import '@testing-library/jest-dom'; +import renderer from 'react-test-renderer'; +import { BrowserRouter as Router } from 'react-router-dom'; +import Content from '../Profile/MainContent/Content/Content'; +import ListingContextProvider from '../../../contexts/ListingContext'; +import Comments from './Comments'; + +it('comments test snapshot', async () => { + const tree = renderer.create( + + + + + + + , + ).toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/MainProfile/Comments/CommentsContent/CommentsContent.jsx b/src/components/MainProfile/Comments/CommentsContent/CommentsContent.jsx index 81b5d74d..4b814c85 100644 --- a/src/components/MainProfile/Comments/CommentsContent/CommentsContent.jsx +++ b/src/components/MainProfile/Comments/CommentsContent/CommentsContent.jsx @@ -91,7 +91,7 @@ function CommentsContent(props) { {comment.parentType !== 'Post' ? : null} - { setEditPost(false); navigate(`/${ownerType === 'Subreddit' ? 'r' : 'user'}/${owner}/comments/${postid}`); }}> + { setEditPost(false); navigate(`/${ownerType === 'Subreddit' ? 'subreddit' : 'user'}/${owner}/comments/${postid}`); }}> {username} {' '} diff --git a/src/components/MainProfile/Comments/CommentsContent/CommentsContent.test.jsx b/src/components/MainProfile/Comments/CommentsContent/CommentsContent.test.jsx index 893f93c6..98277547 100644 --- a/src/components/MainProfile/Comments/CommentsContent/CommentsContent.test.jsx +++ b/src/components/MainProfile/Comments/CommentsContent/CommentsContent.test.jsx @@ -1,10 +1,21 @@ import '@testing-library/jest-dom'; -import renderer from 'react-test-renderer'; import { BrowserRouter as Router } from 'react-router-dom'; +import ShallowRenderer from 'react-test-renderer/shallow'; import MainProfile from '../../MainProfile'; import CommentsContent from './CommentsContent'; +import ListingContextProvider from '../../../../contexts/ListingContext'; test('test snapshot', async () => { - const tree = renderer.create().toJSON(); + const renderer = new ShallowRenderer(); + + const tree = renderer.render( + + + + + + + , + ); expect(tree).toMatchSnapshot(); }); diff --git a/src/components/MainProfile/Comments/CommentsContent/__snapshots__/CommentsContent.test.jsx.snap b/src/components/MainProfile/Comments/CommentsContent/__snapshots__/CommentsContent.test.jsx.snap new file mode 100644 index 00000000..fcb16009 --- /dev/null +++ b/src/components/MainProfile/Comments/CommentsContent/__snapshots__/CommentsContent.test.jsx.snap @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` + + + + + + + +`; diff --git a/src/components/MainProfile/Comments/CommentsHeader/CommentsHeader.test.jsx b/src/components/MainProfile/Comments/CommentsHeader/CommentsHeader.test.jsx index bbc52705..88ad0d0f 100644 --- a/src/components/MainProfile/Comments/CommentsHeader/CommentsHeader.test.jsx +++ b/src/components/MainProfile/Comments/CommentsHeader/CommentsHeader.test.jsx @@ -1,10 +1,21 @@ import '@testing-library/jest-dom'; -import renderer from 'react-test-renderer'; import { BrowserRouter as Router } from 'react-router-dom'; +import ShallowRenderer from 'react-test-renderer/shallow'; import MainProfile from '../../MainProfile'; import CommentsHeader from './CommentsHeader'; +import ListingContextProvider from '../../../../contexts/ListingContext'; test('test snapshot', async () => { - const tree = renderer.create().toJSON(); + const renderer = new ShallowRenderer(); + + const tree = renderer.render( + + + + + + + , + ); expect(tree).toMatchSnapshot(); }); diff --git a/src/components/MainProfile/Comments/CommentsHeader/__snapshots__/CommentsHeader.test.jsx.snap b/src/components/MainProfile/Comments/CommentsHeader/__snapshots__/CommentsHeader.test.jsx.snap new file mode 100644 index 00000000..ec05b281 --- /dev/null +++ b/src/components/MainProfile/Comments/CommentsHeader/__snapshots__/CommentsHeader.test.jsx.snap @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` + + + + + + + +`; diff --git a/src/components/MainProfile/Comments/__snapshots__/Comments.test.jsx.snap b/src/components/MainProfile/Comments/__snapshots__/Comments.test.jsx.snap new file mode 100644 index 00000000..65a20992 --- /dev/null +++ b/src/components/MainProfile/Comments/__snapshots__/Comments.test.jsx.snap @@ -0,0 +1,376 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`comments test snapshot 1`] = ` +
+
+
+ +
+
+ + + +
+
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+
+ + + + + + +
+

+ hmm... u/undefined + hasn't posted recently +

+
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+`; diff --git a/src/components/MainProfile/Comments/styles.js b/src/components/MainProfile/Comments/styles.js index b05e6d44..facc0cb8 100644 --- a/src/components/MainProfile/Comments/styles.js +++ b/src/components/MainProfile/Comments/styles.js @@ -1,4 +1,4 @@ -import { Box, Typography } from '@mui/material'; +import { Box } from '@mui/material'; import { styled } from '@mui/material/styles'; export const PostsQueueBox = styled(Box)(() => ({ @@ -10,9 +10,10 @@ export const PostsQueueBox = styled(Box)(() => ({ position: 'relative', })); -export const CommentText = styled(Typography)(({ theme, coloring, hover }) => ({ +export const CommentText = styled(Box)(({ theme, coloring, hover }) => ({ marginRight: 5, color: coloring, + fontSize: 13, ...((coloring === undefined) && { color: theme.palette.primary.main, }), diff --git a/src/components/MainProfile/CommentsTap/CommentsTap.jsx b/src/components/MainProfile/CommentsTap/CommentsTap.jsx index 6942a3e0..d94a69a5 100644 --- a/src/components/MainProfile/CommentsTap/CommentsTap.jsx +++ b/src/components/MainProfile/CommentsTap/CommentsTap.jsx @@ -3,14 +3,14 @@ import { useContext, useEffect, useState, useMemo, } from 'react'; import { Box } from '@mui/material'; -import InfiniteScroll from 'react-infinite-scroll-component'; +// import InfiniteScroll from 'react-infinite-scroll-component'; import Comments from '../Comments/Comments'; import { postsCommentsServer } from '../profileServer'; import EmptyContent from '../EmptyContent/EmptyContent'; import { UserContext } from '../../../contexts/UserProvider'; import OtherProfileFilter from '../OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilter'; import Filter from '../Profile/MainContent/Filter/Filter'; -import { useListingContext } from '../../../contexts/ListingContext'; +// import { useListingContext } from '../../../contexts/ListingContext'; function useQuery() { const { search } = useLocation(); @@ -18,6 +18,13 @@ function useQuery() { return useMemo(() => new URLSearchParams(search), [search]); } +/** + * CommentsTap + * + * @component Comments + * @returns {React.Component} CommentsTap + */ + function CommentsTap({ profile }) { const { subTitle } = useParams(); const query = useQuery(); @@ -26,10 +33,10 @@ function CommentsTap({ profile }) { const [posts] = postsCommentsServer(username, 'comments', sort || 'new'); const [isContent, setIsContent] = useState(false); - const { setPage } = useListingContext(); - const fetchMoreData = () => { - setPage((page) => page + 1); - }; + // const { setPage } = useListingContext(); + // const fetchMoreData = () => { + // setPage((page) => page + 1); + // }; // check if the page have any content posts to show useEffect(() => { setIsContent(false); @@ -44,14 +51,7 @@ function CommentsTap({ profile }) { {!isContent && } {isContent && ( - - {' '} - {posts.map((entity, index) => ())} - + posts.map((entity, index) => ()) )}
diff --git a/src/components/MainProfile/CommentsTap/CommentsTap.test.jsx b/src/components/MainProfile/CommentsTap/CommentsTap.test.jsx new file mode 100644 index 00000000..ee826537 --- /dev/null +++ b/src/components/MainProfile/CommentsTap/CommentsTap.test.jsx @@ -0,0 +1,21 @@ +import '@testing-library/jest-dom'; +import { BrowserRouter as Router } from 'react-router-dom'; +import ShallowRenderer from 'react-test-renderer/shallow'; +import ListingContextProvider from '../../../contexts/ListingContext'; +import CommentsTap from './CommentsTap'; +import MainProfile from '../MainProfile'; + +test('commentsTap test snapshot', async () => { + const renderer = new ShallowRenderer(); + + const tree = renderer.render( + + + + + + + , + ); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/MainProfile/CommentsTap/__snapshots__/CommentsTap.test.jsx.snap b/src/components/MainProfile/CommentsTap/__snapshots__/CommentsTap.test.jsx.snap new file mode 100644 index 00000000..07524c21 --- /dev/null +++ b/src/components/MainProfile/CommentsTap/__snapshots__/CommentsTap.test.jsx.snap @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`commentsTap test snapshot 1`] = ` + + + + + + + +`; diff --git a/src/components/MainProfile/MainProfile.jsx b/src/components/MainProfile/MainProfile.jsx index 521b55a8..360f2fdd 100644 --- a/src/components/MainProfile/MainProfile.jsx +++ b/src/components/MainProfile/MainProfile.jsx @@ -13,6 +13,14 @@ import UserLogin from '../../authentication'; import ProfileBlocked from './ProfileBlocked/ProfileBlocked'; import cleanPage from '../../utils/cleanPage'; +/** + * MainProfile + * + * @component MainProfile + * @property {function} cleanPage - return number of page to 0 when unmount component + + * @returns {React.Component} MainProfile + */ function MainProfile() { const [cookies] = useCookies(['redditUser']); const [isExist, setIsExist] = useState(true); diff --git a/src/components/MainProfile/MainProfile.test.jsx b/src/components/MainProfile/MainProfile.test.jsx new file mode 100644 index 00000000..482011b2 --- /dev/null +++ b/src/components/MainProfile/MainProfile.test.jsx @@ -0,0 +1,18 @@ +import '@testing-library/jest-dom'; +import { BrowserRouter as Router } from 'react-router-dom'; +import ShallowRenderer from 'react-test-renderer/shallow'; +import MainProfile from './MainProfile'; +import ListingContextProvider from '../../contexts/ListingContext'; + +test('test snapshot', async () => { + const renderer = new ShallowRenderer(); + + const tree = renderer.render( + + + + + , + ); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/MainProfile/ModeratorList/ModerationList.test.jsx b/src/components/MainProfile/ModeratorList/ModerationList.test.jsx new file mode 100644 index 00000000..fc85dfc2 --- /dev/null +++ b/src/components/MainProfile/ModeratorList/ModerationList.test.jsx @@ -0,0 +1,8 @@ +import '@testing-library/jest-dom'; +import renderer from 'react-test-renderer'; +import ModerationList from './ModeratorList'; + +test('Moderation List test snapshot', async () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/MainProfile/ModeratorList/__snapshots__/ModerationList.test.jsx.snap b/src/components/MainProfile/ModeratorList/__snapshots__/ModerationList.test.jsx.snap new file mode 100644 index 00000000..02d09472 --- /dev/null +++ b/src/components/MainProfile/ModeratorList/__snapshots__/ModerationList.test.jsx.snap @@ -0,0 +1,283 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Moderation List test snapshot 1`] = ` +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+`; diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/OtherProfileContent.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/OtherProfileContent.jsx index 9957e30c..23ad9bc9 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/OtherProfileContent.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/OtherProfileContent.jsx @@ -1,6 +1,6 @@ import { useEffect, useState, useMemo } from 'react'; import { useLocation, useParams } from 'react-router-dom'; -import InfiniteScroll from 'react-infinite-scroll-component'; +// import InfiniteScroll from 'react-infinite-scroll-component'; import { overviewServer } from '../../../profileServer'; import EmptyContent from '../OtherProfileEmptyContent/OtherProfileEmptyContent'; import Filter from '../OtherProfileFilter/OtherProfileFilter'; @@ -8,7 +8,7 @@ import ContentBox from './styles'; import Posts from '../../../Posts/Posts'; import Comments from '../../../Comments/Comments'; import mergeTwo from '../../../../../utils/mergeSort'; -import { useListingContext } from '../../../../../contexts/ListingContext'; +// import { useListingContext } from '../../../../../contexts/ListingContext'; function useQuery() { const { search } = useLocation(); @@ -32,10 +32,10 @@ function OtherProfileContent() { const sort = query.get('sort'); const [posts, comments] = overviewServer(username, sort); - const { setPage } = useListingContext(); - const fetchMoreData = () => { - setPage((page) => page + 1); - }; + // const { setPage } = useListingContext(); + // const fetchMoreData = () => { + // setPage((page) => page + 1); + // }; useEffect(() => { setIsContent(false); @@ -51,17 +51,11 @@ function OtherProfileContent() { {!isContent && } {isContent && ( - - {mergeTwo(posts, comments, sort).map((entity, index) => ( + mergeTwo(posts, comments, sort).map((entity, index) => ( (!entity.comments) ? : (entity.author.name === username) ? : - ))} - + )) )} ); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/OtherProfileContent.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/OtherProfileContent.test.jsx index ab682d82..3947019a 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/OtherProfileContent.test.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/OtherProfileContent.test.jsx @@ -1,10 +1,21 @@ import '@testing-library/jest-dom'; -import renderer from 'react-test-renderer'; import { BrowserRouter as Router } from 'react-router-dom'; +import ShallowRenderer from 'react-test-renderer/shallow'; import OtherProfileMainContent from '../OtherProfileMainContent'; import OtherProfileContent from './OtherProfileContent'; +import ListingContextProvider from '../../../../../contexts/ListingContext'; test('test snapshot', async () => { - const tree = renderer.create().toJSON(); + const renderer = new ShallowRenderer(); + + const tree = renderer.render( + + + + + + + , + ); expect(tree).toMatchSnapshot(); }); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/__snapshots__/OtherProfileContent.test.jsx.snap b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/__snapshots__/OtherProfileContent.test.jsx.snap index e4339b09..cd945144 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/__snapshots__/OtherProfileContent.test.jsx.snap +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileContent/__snapshots__/OtherProfileContent.test.jsx.snap @@ -1,616 +1,40 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`test snapshot 1`] = ` -
-
-
-
-
- -
-
- - - -
-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
- - - - - - -
-

- hmm... u/undefined - hasn't posted recently -

-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
-
- cover image -
-
-
- user photo -
-
- - u/ - -
- -
-
-

- Karma -

-
- - - - - NaN - -
-
-
-

- Cake Day -

-
- - - - - Invalid date - -
-
-
-
- - -
- -
-
-
-

- Moderator of these communities -

-
- -
-
-
+ + + + + + `; diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilter.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilter.test.jsx index 12e46fc7..d6c72a81 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilter.test.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilter.test.jsx @@ -1,10 +1,21 @@ import '@testing-library/jest-dom'; -import renderer from 'react-test-renderer'; import { BrowserRouter as Router } from 'react-router-dom'; +import ShallowRenderer from 'react-test-renderer/shallow'; import OtherProfileMainContent from '../OtherProfileMainContent'; import OtherProfileFilter from './OtherProfileFilter'; +import ListingContextProvider from '../../../../../contexts/ListingContext'; test('test snapshot', async () => { - const tree = renderer.create().toJSON(); + const renderer = new ShallowRenderer(); + + const tree = renderer.render( + + + + + + + , + ); expect(tree).toMatchSnapshot(); }); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilterFull/OtherProfileFilterFull.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilterFull/OtherProfileFilterFull.test.jsx index 1c9fd0e6..5f27e914 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilterFull/OtherProfileFilterFull.test.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilterFull/OtherProfileFilterFull.test.jsx @@ -1,10 +1,21 @@ import '@testing-library/jest-dom'; -import renderer from 'react-test-renderer'; import { BrowserRouter as Router } from 'react-router-dom'; +import ShallowRenderer from 'react-test-renderer/shallow'; import OtherProfileMainContent from '../../OtherProfileMainContent'; import OtherProfileFilterFull from './OtherProfileFilterFull'; +import ListingContextProvider from '../../../../../../contexts/ListingContext'; test('test snapshot', async () => { - const tree = renderer.create().toJSON(); + const renderer = new ShallowRenderer(); + + const tree = renderer.render( + + + + + + + , + ); expect(tree).toMatchSnapshot(); }); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilterFull/__snapshots__/OtherProfileFilterFull.test.jsx.snap b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilterFull/__snapshots__/OtherProfileFilterFull.test.jsx.snap index e4339b09..3cd0f978 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilterFull/__snapshots__/OtherProfileFilterFull.test.jsx.snap +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/OtherProfileFilterFull/__snapshots__/OtherProfileFilterFull.test.jsx.snap @@ -1,616 +1,40 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`test snapshot 1`] = ` -
-
-
-
-
- -
-
- - - -
-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
- - - - - - -
-

- hmm... u/undefined - hasn't posted recently -

-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
-
- cover image -
-
-
- user photo -
-
- - u/ - -
- -
-
-

- Karma -

-
- - - - - NaN - -
-
-
-

- Cake Day -

-
- - - - - Invalid date - -
-
-
-
- - -
- -
-
-
-

- Moderator of these communities -

-
- -
-
-
+ + + + + + `; diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/__snapshots__/OtherProfileFilter.test.jsx.snap b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/__snapshots__/OtherProfileFilter.test.jsx.snap index e4339b09..83b78968 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/__snapshots__/OtherProfileFilter.test.jsx.snap +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileFilter/__snapshots__/OtherProfileFilter.test.jsx.snap @@ -1,616 +1,40 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`test snapshot 1`] = ` -
-
-
-
-
- -
-
- - - -
-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
- - - - - - -
-

- hmm... u/undefined - hasn't posted recently -

-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
-
- cover image -
-
-
- user photo -
-
- - u/ - -
- -
-
-

- Karma -

-
- - - - - NaN - -
-
-
-

- Cake Day -

-
- - - - - Invalid date - -
-
-
-
- - -
- -
-
-
-

- Moderator of these communities -

-
- -
-
-
+ + + + + + `; diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileMainContent.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileMainContent.test.jsx index 1488f117..6211e560 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileMainContent.test.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileMainContent.test.jsx @@ -6,9 +6,16 @@ import { } from '@testing-library/react'; import { BrowserRouter as Router } from 'react-router-dom'; import OtherProfileMainContent from './OtherProfileMainContent'; +import ListingContextProvider from '../../../../contexts/ListingContext'; it('open posts tap', async () => { - render(); + render( + + + + + , + ); const photo = screen.getByTestId('cover-photo'); expect(photo).toBeInTheDocument(); }); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfileArrowList/OtherProfileArrowList.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfileArrowList/OtherProfileArrowList.test.jsx new file mode 100644 index 00000000..9937b2cd --- /dev/null +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfileArrowList/OtherProfileArrowList.test.jsx @@ -0,0 +1,10 @@ +import '@testing-library/jest-dom'; +import renderer from 'react-test-renderer'; +import OtherProfileArrowList from './OtherProfileArrowList'; + +test('test snapshot', async () => { + const tree = renderer.create( + , + ).toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfileArrowList/__snapshots__/OtherProfileArrowList.test.jsx.snap b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfileArrowList/__snapshots__/OtherProfileArrowList.test.jsx.snap new file mode 100644 index 00000000..532e6b5b --- /dev/null +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfileArrowList/__snapshots__/OtherProfileArrowList.test.jsx.snap @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` +
+ + + + + + + +
+`; diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooter.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooter.jsx index ec4c585d..fcbc571a 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooter.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooter.jsx @@ -16,7 +16,6 @@ import FlagOutlinedIcon from '@mui/icons-material/FlagOutlined'; import BookmarksOutlinedIcon from '@mui/icons-material/BookmarksOutlined'; import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { useNavigate } from 'react-router-dom'; -import { usePostTypeContext } from '../../../../../../contexts/PostTypeContext'; import { ElementBox, FooterBox, FooterText, } from './styles'; @@ -25,6 +24,8 @@ import OtherProfileArrowList from './OtherProfileArrowList/OtherProfileArrowList import { postReactionsServer } from '../../../../profileServer'; import ModeratorList from '../../../../ModeratorList/ModeratorList'; +import { useEditPostContext } from '../../../../../../contexts/EditPostContext'; + /** * Footer of the post that contain all icons * @@ -36,8 +37,8 @@ import ModeratorList from '../../../../ModeratorList/ModeratorList'; */ function OtherProfilePostFooter(props) { const { - postid, numComments, handleExpand, expand, saved, hidden, submitted, - points, postVoteStatus, owner, ownerType, isModList, modState, nsfw, spoiler, locked, + postid, numComments, handleExpand, expand, saved, hidden, submitted, ownerType, owner, + points, postVoteStatus, isModList, modState, nsfw, spoiler, locked, handleLock, handleSpoiler, handleNsfw, handleApprove, handleRemove, handleSpam, } = props; const [isHidden, setIsHidden] = useState(hidden); @@ -46,6 +47,9 @@ function OtherProfilePostFooter(props) { const [modList, setModList] = useState(false); const [moderatorList, setModeratorList] = useState(false); + const navigate = useNavigate(); + const { setEditPost, setCommentPost } = useEditPostContext(); + // handle disable the list when click away const handleClick2 = () => { setShowList2((prev) => !prev); @@ -75,25 +79,8 @@ function OtherProfilePostFooter(props) { setIsSaved((prev) => !prev); }; - const getPostUrl = () => { - const username = owner; - if (ownerType === 'User') { - if (username) { - return `user/${username}/comments/${postid}`; - } - return ''; - } - return `r/${owner}/comments/${postid}`; - }; - - const { setInitialPostUrl, setInitialPostType } = usePostTypeContext(); - const { REACT_APP_ENV, REACT_APP_WEB_PRO, REACT_APP_WEB_DEV } = process.env; - const navigate = useNavigate(); - const handleShare = () => { - setInitialPostUrl((REACT_APP_ENV === 'development' ? REACT_APP_WEB_DEV : REACT_APP_WEB_PRO) + getPostUrl()); - setInitialPostType(3); - navigate('/submit'); + navigate(`/submit/${postid}`); }; useEffect(() => { @@ -135,7 +122,8 @@ function OtherProfilePostFooter(props) { {/* number of comments and share section */} - + + { setCommentPost(true); setEditPost(false); navigate(`/${ownerType === 'Subreddit' ? 'r' : 'user'}/${owner}/comments/${postid}`); }}> {numComments} diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooter.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooter.test.jsx index aa204a35..d5e59489 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooter.test.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooter.test.jsx @@ -1,8 +1,16 @@ import '@testing-library/jest-dom'; import renderer from 'react-test-renderer'; +import { BrowserRouter as Router } from 'react-router-dom'; import OtherProfilePostFooter from './OtherProfilePostFooter'; +import EditPostContextProvider from '../../../../../../contexts/EditPostContext'; test('test snapshot', async () => { - const tree = renderer.create().toJSON(); + const tree = renderer.create( + + + + + , + ).toJSON(); expect(tree).toMatchSnapshot(); }); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooterListResponsive/OtherProfilePostFooterListResponsive.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooterListResponsive/OtherProfilePostFooterListResponsive.test.jsx index e273ccf6..51c6d984 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooterListResponsive/OtherProfilePostFooterListResponsive.test.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooterListResponsive/OtherProfilePostFooterListResponsive.test.jsx @@ -1,10 +1,10 @@ import '@testing-library/jest-dom'; import renderer from 'react-test-renderer'; -import { BrowserRouter as Router } from 'react-router-dom'; -import OtherProfileMainContent from '../../../OtherProfileMainContent'; import OtherProfilePostFooterListResponsive from './OtherProfilePostFooterListResponsive'; test('test snapshot', async () => { - const tree = renderer.create().toJSON(); + const tree = renderer.create( + , + ).toJSON(); expect(tree).toMatchSnapshot(); }); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooterListResponsive/__snapshots__/OtherProfilePostFooterListResponsive.test.jsx.snap b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooterListResponsive/__snapshots__/OtherProfilePostFooterListResponsive.test.jsx.snap index e4339b09..2a28e4a6 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooterListResponsive/__snapshots__/OtherProfilePostFooterListResponsive.test.jsx.snap +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/OtherProfilePostFooterListResponsive/__snapshots__/OtherProfilePostFooterListResponsive.test.jsx.snap @@ -2,615 +2,108 @@ exports[`test snapshot 1`] = `
-
-
-
-
- -
-
- - - -
-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
- - - - - - -
-

- hmm... u/undefined - hasn't posted recently -

-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
+ + Save + +
+ +
+ -
-
-

- Karma -

-
- - - - - NaN - -
-
-
-

- Cake Day -

-
- - - - - Invalid date - -
-
-
-
- - -
- -
-
-
-

- Moderator of these communities -

-
- -
- + + + Report + `; diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/__snapshots__/OtherProfilePostFooter.test.jsx.snap b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/__snapshots__/OtherProfilePostFooter.test.jsx.snap index 1039a658..b5935c34 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/__snapshots__/OtherProfilePostFooter.test.jsx.snap +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfileFooter/__snapshots__/OtherProfilePostFooter.test.jsx.snap @@ -56,6 +56,7 @@ exports[`test snapshot 1`] = ` />
-
- - - - - Report - -
- { setEditPost(false); navigate(`/${entity?.ownerType === 'Subreddit' ? 'r' : 'user'}/${entity?.owner?.name}/comments/${entity?._id}`); }}> + { setEditPost(false); navigate(`/${entity?.ownerType === 'Subreddit' ? 'subreddit' : 'user'}/${entity?.owner?.name}/comments/${entity?._id}`); }}> {entity.images.length === 0 ? ( @@ -105,7 +105,7 @@ function OtherProfilePost(props) { - { setEditPost(false); navigate(`/${entity?.ownerType === 'Subreddit' ? 'r' : 'user'}/${entity?.owner?.name}/comments/${entity?._id}`); }}> + { setEditPost(false); navigate(`/${entity?.ownerType === 'Subreddit' ? 'subreddit' : 'user'}/${entity?.owner?.name}/comments/${entity?._id}`); }}> {entity.title} { entity?.flairId?.text @@ -143,8 +143,6 @@ function OtherProfilePost(props) { numComments={entity.commentCount} points={entity.votes} postVoteStatus={entity.postVoteStatus} - owner={entity.owner.name} - ownerType={entity.ownerType} nsfw={isNsfw} spoiler={isSpoiler} locked={isLocked} @@ -156,6 +154,8 @@ function OtherProfilePost(props) { handleApprove={handleApprove} handleRemove={handleRemove} handleSpam={handleSpam} + ownerType={entity.ownerType} + owner={entity.owner.name} /> diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostHeader/OtherProfilePostHeader.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostHeader/OtherProfilePostHeader.test.jsx index aa6b0c71..e44b2dd5 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostHeader/OtherProfilePostHeader.test.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostHeader/OtherProfilePostHeader.test.jsx @@ -1,10 +1,13 @@ import '@testing-library/jest-dom'; import renderer from 'react-test-renderer'; import { BrowserRouter as Router } from 'react-router-dom'; -import OtherProfileMainContent from '../../OtherProfileMainContent'; import OtherProfilePostHeader from './OtherProfilePostHeader'; test('test snapshot', async () => { - const tree = renderer.create().toJSON(); + const tree = renderer.create( + + + , + ).toJSON(); expect(tree).toMatchSnapshot(); }); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostHeader/__snapshots__/OtherProfilePostHeader.test.jsx.snap b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostHeader/__snapshots__/OtherProfilePostHeader.test.jsx.snap index e4339b09..db6da80d 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostHeader/__snapshots__/OtherProfilePostHeader.test.jsx.snap +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostHeader/__snapshots__/OtherProfilePostHeader.test.jsx.snap @@ -2,615 +2,42 @@ exports[`test snapshot 1`] = `
-
-
-
-
- -
-
- - - -
-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
- - - - - - -
-

- hmm... u/undefined - hasn't posted recently -

-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
- -
+ u/ + + + + + a few seconds ago +
`; diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostSide/OtherProfilePostSide.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostSide/OtherProfilePostSide.test.jsx index 03be21d7..492a8bf9 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostSide/OtherProfilePostSide.test.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostSide/OtherProfilePostSide.test.jsx @@ -1,10 +1,10 @@ import '@testing-library/jest-dom'; import renderer from 'react-test-renderer'; -import { BrowserRouter as Router } from 'react-router-dom'; -import OtherProfileMainContent from '../../OtherProfileMainContent'; import OtherProfilePostSide from './OtherProfilePostSide'; test('test snapshot', async () => { - const tree = renderer.create().toJSON(); + const tree = renderer.create( + , + ).toJSON(); expect(tree).toMatchSnapshot(); }); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostSide/__snapshots__/OtherProfilePostSide.test.jsx.snap b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostSide/__snapshots__/OtherProfilePostSide.test.jsx.snap index e4339b09..76e05bce 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostSide/__snapshots__/OtherProfilePostSide.test.jsx.snap +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePostSide/__snapshots__/OtherProfilePostSide.test.jsx.snap @@ -2,615 +2,34 @@ exports[`test snapshot 1`] = `
-
-
-
-
- -
-
- - - -
-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
- - - - - - -
-

- hmm... u/undefined - hasn't posted recently -

-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
-
- cover image -
-
-
- user photo -
-
- - u/ - -
- -
-
-

- Karma -

-
- - - - - NaN - -
-
-
-

- Cake Day -

-
- - - - - Invalid date - -
-
-
-
- - -
- -
-
-
-

- Moderator of these communities -

-
- -
-
+ + + + + +
`; diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePosts.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePosts.test.jsx index 5b7c7f9e..a27cbdab 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePosts.test.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/OtherProfilePosts.test.jsx @@ -1,10 +1,21 @@ import '@testing-library/jest-dom'; -import renderer from 'react-test-renderer'; import { BrowserRouter as Router } from 'react-router-dom'; +import ShallowRenderer from 'react-test-renderer/shallow'; import OtherProfileMainContent from '../OtherProfileMainContent'; import OtherProfilePost from './OtherProfilePost'; +import ListingContextProvider from '../../../../../contexts/ListingContext'; test('test snapshot', async () => { - const tree = renderer.create().toJSON(); + const renderer = new ShallowRenderer(); + + const tree = renderer.render( + + + + + + + , + ); expect(tree).toMatchSnapshot(); }); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/__snapshots__/OtherProfilePosts.test.jsx.snap b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/__snapshots__/OtherProfilePosts.test.jsx.snap index e4339b09..3ff71f20 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/__snapshots__/OtherProfilePosts.test.jsx.snap +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePosts/__snapshots__/OtherProfilePosts.test.jsx.snap @@ -1,616 +1,40 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`test snapshot 1`] = ` -
-
-
-
-
- -
-
- - - -
-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
- - - - - - -
-

- hmm... u/undefined - hasn't posted recently -

-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
-
- cover image -
-
-
- user photo -
-
- - u/ - -
- -
-
-

- Karma -

-
- - - - - NaN - -
-
-
-

- Cake Day -

-
- - - - - Invalid date - -
-
-
-
- - -
- -
-
-
-

- Moderator of these communities -

-
- -
-
-
+ + + + + + `; diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/OtherProfilePostsTap.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/OtherProfilePostsTap.jsx index 9bbf84ec..abf5d4a4 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/OtherProfilePostsTap.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/OtherProfilePostsTap.jsx @@ -1,12 +1,12 @@ import { useLocation, useParams } from 'react-router-dom'; import { useEffect, useState, useMemo } from 'react'; -import InfiniteScroll from 'react-infinite-scroll-component'; +// import InfiniteScroll from 'react-infinite-scroll-component'; import { postsCommentsServer } from '../../../profileServer'; import Filter from '../OtherProfileFilter/OtherProfileFilter'; import { WideBox } from '../styles'; import EmptyContent from '../OtherProfileEmptyContent/OtherProfileEmptyContent'; import Post from '../OtherProfilePosts/OtherProfilePost'; -import { useListingContext } from '../../../../../contexts/ListingContext'; +// import { useListingContext } from '../../../../../contexts/ListingContext'; function useQuery() { const { search } = useLocation(); @@ -27,11 +27,6 @@ function OtherProfilePostsTap() { const [posts] = postsCommentsServer(username, 'posts', sort || 'new'); const [isContent, setIsContent] = useState(false); - const { setPage } = useListingContext(); - const fetchMoreData = () => { - setPage((page) => page + 1); - }; - // check if the page have any content posts to show useEffect(() => { console.log(posts); @@ -47,13 +42,7 @@ function OtherProfilePostsTap() { {!isContent && } {isContent && ( - - {posts.map((entity, index) => ())} - + posts.map((entity, index) => ()) )} diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/OtherProfilePostsTap.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/OtherProfilePostsTap.test.jsx index 3a7c902e..9ea6a35a 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/OtherProfilePostsTap.test.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/OtherProfilePostsTap.test.jsx @@ -1,16 +1,21 @@ import '@testing-library/jest-dom'; -import { render } from '@testing-library/react'; import { BrowserRouter as Router } from 'react-router-dom'; -import renderer from 'react-test-renderer'; +import ShallowRenderer from 'react-test-renderer/shallow'; import OtherProfileMainContent from '../OtherProfileMainContent'; import OtherProfilePostsTap from './OtherProfilePostsTap'; +import ListingContextProvider from '../../../../../contexts/ListingContext'; test('test snapshot', async () => { - const tree = renderer.create().toJSON(); - expect(tree).toMatchSnapshot(); -}); + const renderer = new ShallowRenderer(); -test('test snapshot', async () => { - render(); -// expect(tree).toMatchSnapshot(); + const tree = renderer.render( + + + + + + + , + ); + expect(tree).toMatchSnapshot(); }); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/__snapshots__/OtherProfilePostsTap.test.jsx.snap b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/__snapshots__/OtherProfilePostsTap.test.jsx.snap index e4339b09..fc3d5803 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/__snapshots__/OtherProfilePostsTap.test.jsx.snap +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfilePostsTap/__snapshots__/OtherProfilePostsTap.test.jsx.snap @@ -1,616 +1,40 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`test snapshot 1`] = ` -
-
-
-
-
- -
-
- - - -
-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
- - - - - - -
-

- hmm... u/undefined - hasn't posted recently -

-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
-
- cover image -
-
-
- user photo -
-
- - u/ - -
- -
-
-

- Karma -

-
- - - - - NaN - -
-
-
-

- Cake Day -

-
- - - - - Invalid date - -
-
-
-
- - -
- -
-
-
-

- Moderator of these communities -

-
- -
-
-
+ + + + + + `; diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/BackHomeBottun/BackHome.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/BackHomeBottun/BackHome.jsx index dd070916..2efd4a15 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/BackHomeBottun/BackHome.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/BackHomeBottun/BackHome.jsx @@ -2,6 +2,13 @@ import { Box } from '@mui/system'; // eslint-disable-next-line import/no-named-as-default import BackHome from './style'; +/** + * BackHomeBottun component shows all comments over a post + * + * @component BackHomeBottun + * @property {fundtion} goToTop - return to the top of the page + * @returns {React.Component} BackHomeBottun + */ function BackHomeBottun() { function goToTop() { document.documentElement.scrollTop = 0; diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/OtherProfileCommunities.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/OtherProfileCommunities.test.jsx index a84ca2bf..eb340e88 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/OtherProfileCommunities.test.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/OtherProfileCommunities.test.jsx @@ -1,10 +1,21 @@ import '@testing-library/jest-dom'; -import renderer from 'react-test-renderer'; import { BrowserRouter as Router } from 'react-router-dom'; +import ShallowRenderer from 'react-test-renderer/shallow'; import OtherProfileMainContent from '../../OtherProfileMainContent'; import OtherProfileCommunities from './OtherProfileCommunities'; +import ListingContextProvider from '../../../../../../contexts/ListingContext'; test('test snapshot', async () => { - const tree = renderer.create().toJSON(); + const renderer = new ShallowRenderer(); + + const tree = renderer.render( + + + + + + + , + ); expect(tree).toMatchSnapshot(); }); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/OtherProfileEntityCommunity/OtherProfileEntityCommunity.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/OtherProfileEntityCommunity/OtherProfileEntityCommunity.jsx index 83002324..3c8fc39d 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/OtherProfileEntityCommunity/OtherProfileEntityCommunity.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/OtherProfileEntityCommunity/OtherProfileEntityCommunity.jsx @@ -6,7 +6,16 @@ import { CommunitiesSubscriberContext } from '../../../../../../../contexts/Comm import { ComminityBox, HeaderAvatar, HeaderAvatarImage, Joined, SubReddit, } from './styles'; - +/** + * OtherProfileEntityComment component shows all comments over a post + * + * @component OtherProfileEntityComment + * @property {object} community - entity + * @property {boolean} handleJoin - sharing their state currently + * @property {boolean} handleMouseIn - show text when hover + * @property {boolean} handleMouseOut - retyrn the text to its default state + * @returns {React.Component} OtherProfileEntityComment + */ function OtherProfileEntityComment(props) { const { community } = props; const { communitiesSubscriber } = useContext(CommunitiesSubscriberContext); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/__snapshots__/OtherProfileCommunities.test.jsx.snap b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/__snapshots__/OtherProfileCommunities.test.jsx.snap index e4339b09..f45e1950 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/__snapshots__/OtherProfileCommunities.test.jsx.snap +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileCommunities/__snapshots__/OtherProfileCommunities.test.jsx.snap @@ -1,616 +1,40 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`test snapshot 1`] = ` -
-
-
-
-
- -
-
- - - -
-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
- - - - - - -
-

- hmm... u/undefined - hasn't posted recently -

-
-
- - - - - - -
-
- - - - - - -
-
- - - - - - -
-
-
-
- cover image -
-
-
- user photo -
-
- - u/ - -
- -
-
-

- Karma -

-
- - - - - NaN - -
-
-
-

- Cake Day -

-
- - - - - Invalid date - -
-
-
-
- - -
- -
-
-
-

- Moderator of these communities -

-
- -
-
-
+ + + + + + `; diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileSidebar.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileSidebar.test.jsx new file mode 100644 index 00000000..26496e9b --- /dev/null +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileSidebar.test.jsx @@ -0,0 +1,12 @@ +import '@testing-library/jest-dom'; +import ShallowRenderer from 'react-test-renderer/shallow'; +import OtherProfileSidebar from './OtherProfileSidebar'; + +test('test snapshot', async () => { + const renderer = new ShallowRenderer(); + + const tree = renderer.render( + , + ); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/Block/Block.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/Block/Block.jsx index c176a565..03ad9ab0 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/Block/Block.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/Block/Block.jsx @@ -6,6 +6,12 @@ import CloseIcon from '@mui/icons-material/Close'; import { Typography } from '@mui/material'; import { DialogButtons } from './styles'; +/** + * Block + * + * @component Block + * @returns {React.Component} Block + */ function Block({ onClose, username, handleBlock }) { return ( <> diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/Block/Block.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/Block/Block.test.jsx new file mode 100644 index 00000000..e38f376c --- /dev/null +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/Block/Block.test.jsx @@ -0,0 +1,10 @@ +import '@testing-library/jest-dom'; +import renderer from 'react-test-renderer'; +import Block from './Block'; + +test('test snapshot', async () => { + const tree = renderer.create( + , + ).toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/Block/__snapshots__/Block.test.jsx.snap b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/Block/__snapshots__/Block.test.jsx.snap new file mode 100644 index 00000000..129cbd0c --- /dev/null +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/Block/__snapshots__/Block.test.jsx.snap @@ -0,0 +1,66 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` +Array [ +

+ Unblock u/ + ? +

, +
+

+ They wonโ€™t be notified, but theyโ€™ll be able to message you, follow you, and youโ€™ll start seeing notifications from them. You wonโ€™t be able to block them again for 24 hours. +

+
, +
+ + +
, +] +`; diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/OtherProfileUserInfo.test.jsx b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/OtherProfileUserInfo.test.jsx index c2cee96d..f618d4f7 100644 --- a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/OtherProfileUserInfo.test.jsx +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/OtherProfileUserInfo/OtherProfileUserInfo.test.jsx @@ -6,9 +6,18 @@ import { import { BrowserRouter as Router } from 'react-router-dom'; import OtherProfileMainContent from '../../OtherProfileMainContent'; import OtherProfileUserInfo from './OtherProfileUserInfo'; +import ListingContextProvider from '../../../../../../contexts/ListingContext'; it('open posts tap', async () => { - render(); + render( + + + + + + + , + ); const btn = screen.getByTestId('show-more'); fireEvent.click(btn); const cancelHidden = screen.getByTestId('option'); diff --git a/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/__snapshots__/OtherProfileSidebar.test.jsx.snap b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/__snapshots__/OtherProfileSidebar.test.jsx.snap new file mode 100644 index 00000000..af9cfde2 --- /dev/null +++ b/src/components/MainProfile/OtherProfile/OtherProfileMainContent/OtherProfileSidebar/__snapshots__/OtherProfileSidebar.test.jsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` + + + + + +`; diff --git a/src/components/MainProfile/Posts/CrossPost.jsx/CrossPost.jsx b/src/components/MainProfile/Posts/CrossPost.jsx/CrossPost.jsx index 2e6b0df1..bba32573 100644 --- a/src/components/MainProfile/Posts/CrossPost.jsx/CrossPost.jsx +++ b/src/components/MainProfile/Posts/CrossPost.jsx/CrossPost.jsx @@ -11,6 +11,13 @@ import { CommunitiesSubscriberContext } from '../../../../contexts/CommunitiesSu import PostBody from '../PostBody/PostBody'; import { LinkCross } from '../PostHeader/styles'; +/** + * CrossPost + * + * @component CrossPost + * @returns {React.Component} CrossPost + */ + function CrossPost({ post }) { // const [isSpoiler, setIsSpoiler] = useState(); // const [isLocked, setIsLocked] = useState(); diff --git a/src/components/MainProfile/Posts/CrossPost.jsx/CrossPost.test.jsx b/src/components/MainProfile/Posts/CrossPost.jsx/CrossPost.test.jsx new file mode 100644 index 00000000..7d428fa0 --- /dev/null +++ b/src/components/MainProfile/Posts/CrossPost.jsx/CrossPost.test.jsx @@ -0,0 +1,24 @@ +import '@testing-library/jest-dom'; +import { BrowserRouter as Router } from 'react-router-dom'; +import ShallowRenderer from 'react-test-renderer/shallow'; +import ProfileMainContent from '../../Profile/MainContent/ProfileMainContent'; +import EditPostContextProvider from '../../../../contexts/EditPostContext'; +import ListingContextProvider from '../../../../contexts/ListingContext'; +import CrossPost from './CrossPost'; + +test('test snapshot', async () => { + const renderer = new ShallowRenderer(); + + const tree = renderer.render( + + + + + + + + + , + ); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/MainProfile/Posts/CrossPost.jsx/__snapshots__/CrossPost.test.jsx.snap b/src/components/MainProfile/Posts/CrossPost.jsx/__snapshots__/CrossPost.test.jsx.snap new file mode 100644 index 00000000..95def780 --- /dev/null +++ b/src/components/MainProfile/Posts/CrossPost.jsx/__snapshots__/CrossPost.test.jsx.snap @@ -0,0 +1,42 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test snapshot 1`] = ` + + + + + + + + + +`; diff --git a/src/components/MainProfile/Posts/PostBody/PostBody.jsx b/src/components/MainProfile/Posts/PostBody/PostBody.jsx index a47f2dff..0461f106 100644 --- a/src/components/MainProfile/Posts/PostBody/PostBody.jsx +++ b/src/components/MainProfile/Posts/PostBody/PostBody.jsx @@ -12,7 +12,13 @@ import { PostMedia, } from '../styles'; import { useEditPostContext } from '../../../../contexts/EditPostContext'; - +/** + * PostBody + * + * @component PostBody + * @property {function} handleDirection switch between images + * @returns {React.Component} PostBody + */ function PostBody({ post, isSpoiler }) { const [maxImagesHeight, setMaxImagesHeight] = useState(450); @@ -24,6 +30,7 @@ function PostBody({ post, isSpoiler }) { const { setEditPost } = useEditPostContext(); useEffect(() => { + console.log(post.images); post.images?.forEach((image) => { const img = new Image(); img.src = image; @@ -57,7 +64,7 @@ function PostBody({ post, isSpoiler }) { > {post?.kind === 'video' ? ( // eslint-disable-next-line jsx-a11y/media-has-caption -