Ignore:
Timestamp:
10/27/22 17:35:03 (2 years ago)
Author:
unknown <mlviktor23@…>
Branches:
main
Children:
3b6962d
Parents:
8d83180
Message:

left: moderation, oAuth, messaging

Location:
reactapp/src/Components
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • reactapp/src/Components/OpinionTree.js

    r8d83180 rc68150f  
    33  OpinionCardContent,
    44  OpinionCardContentTime,
    5   OpinionCardContentTitle,
    65  OpinionReplyCard,
    76  OpinionReplyCardContent,
     
    1413import AuthApi from "../api/AuthApi";
    1514import { useNavigate } from "react-router-dom";
    16 import { useContext, useState } from "react";
     15import { useContext, useState, useEffect } from "react";
     16import JSOG from "jsog";
    1717import {
    1818  Modal,
     
    2626import axios from "../api/axios";
    2727
    28 function OpinionTree({ professor, user, userLoaded }) {
     28function OpinionTree({ professor }) {
    2929  var renderedOpinionIds = [];
    3030  var postCount; // za da ne go pokazuva ispod postot
    3131
     32  const { auth, setAuth } = useContext(AuthApi);
    3233  let navigate = useNavigate();
    33   const { auth, setAuth } = useContext(AuthApi);
    34 
    35   let [replyModalDisplay, setReplyModalDisplay] = useState("none");
     34
     35  const [replyModalDisplay, setReplyModalDisplay] = useState("none");
    3636  const [replyContent, setReplyContent] = useState("");
    37 
    3837  const [postForModal, setPostForModal] = useState(null);
     38  const [user, setUser] = useState(null);
     39  const [loadedUser, setLoadedUser] = useState(false);
     40  const [fetchError, setFetchError] = useState(false);
     41  const [errorMessage, setErrorMessage] = useState("");
     42
     43  useEffect(() => {
     44    const url = `http://192.168.0.17:8080/secure/currentUser`;
     45
     46    const fetchUser = async () => {
     47      try {
     48        const response = await axios.get(url, { withCredentials: true });
     49        var cyclicGraph = await response.data;
     50        var jsogStructure = JSOG.encode(cyclicGraph);
     51        cyclicGraph = JSOG.decode(jsogStructure);
     52        setUser(cyclicGraph);
     53        setLoadedUser(true);
     54      } catch (error) {
     55        setFetchError(true);
     56      }
     57    };
     58
     59    if (auth) fetchUser();
     60  }, []);
    3961
    4062  const handleLike = async (post) => {
    41     if (
    42       auth &&
    43       userLoaded &&
    44       !post.likes.some((e) => e.id === user.user.id) &&
    45       !post.dislikes.some((e) => e.id === user.user.id)
    46     ) {
    47       const response = await axios(
    48         `http://192.168.0.17:8080/secure/professor/${professor.professorId}/upvoteOpinion/${post.postId}`,
    49         {
    50           method: "get",
    51           withCredentials: true,
    52         }
    53       );
    54 
    55       window.location.reload(false);
     63    if (auth) {
     64      if (
     65        loadedUser &&
     66        user &&
     67        !post.votes.some((e) => e.user.id === user.id)
     68      ) {
     69        const response = await axios(
     70          `http://192.168.0.17:8080/secure/upvoteOpinion/${post.postId}`,
     71          {
     72            method: "get",
     73            withCredentials: true,
     74          }
     75        );
     76        window.location.reload(false);
     77      } else {
     78        return;
     79      }
    5680    } else {
    57       return;
     81      navigate("/login");
    5882    }
    5983  };
    6084
    6185  const handleDislike = async (post) => {
    62     if (
    63       auth &&
    64       auth &&
    65       userLoaded &&
    66       !post.likes.some((e) => e.id === user.user.id) &&
    67       !post.dislikes.some((e) => e.id === user.user.id)
    68     ) {
    69       const response = await axios(
    70         `http://192.168.0.17:8080/secure/professor/${professor.professorId}/downvoteOpinion/${post.postId}`,
    71         {
    72           method: "get",
    73           withCredentials: true,
    74         }
    75       );
    76 
    77       window.location.reload(false);
     86    if (auth) {
     87      if (
     88        loadedUser &&
     89        user &&
     90        !post.votes.some((e) => e.user.id === user.id)
     91      ) {
     92        const response = await axios(
     93          `http://192.168.0.17:8080/secure/downvoteOpinion/${post.postId}`,
     94          {
     95            method: "get",
     96            withCredentials: true,
     97          }
     98        );
     99
     100        window.location.reload(false);
     101      } else {
     102        return;
     103      }
    78104    } else {
    79       return;
     105      navigate("/login");
    80106    }
    81107  };
     
    101127    e.preventDefault();
    102128
    103     const response = await axios(
    104       `http://192.168.0.17:8080/secure/professor/${professor.professorId}/replyToOpinion/${postId}`,
    105       {
    106         method: "post",
    107         body: {
    108           content: replyContent,
    109         },
    110         withCredentials: true,
    111       }
    112     );
    113 
    114     window.location.reload(false);
    115     //console.log(response);
     129    if (!replyContent.length < 1) {
     130      const response = await axios(
     131        `http://192.168.0.17:8080/secure/professor/${professor.professorId}/replyToOpinion/${postId}`,
     132        {
     133          method: "post",
     134          data: {
     135            content: replyContent,
     136          },
     137          withCredentials: true,
     138        }
     139      );
     140      setErrorMessage("");
     141      window.location.reload(false);
     142    } else {
     143      setErrorMessage("Полето за содржина не смее да биде празно");
     144    }
    116145  };
    117146
     
    123152        <OpinionReplyCard indent={replyIndent + "px"}>
    124153          <OpinionReplyCardContent>
    125             <p>
    126               <a href="#">{child.author.username}</a> му реплицирал на{" "}
    127               {parentPostAuthorUsername}
     154            <p style={{ fontStyle: "italic", marginBottom: "10px" }}>
     155              <a href={"/user/" + child.author.id}>{child.author.username}</a>{" "}
     156              му реплицирал на {parentPostAuthorUsername}
    128157            </p>
    129             <p>{child.content}</p>
     158            <p style={{ marginBottom: "10px", maxWidth: "90%" }}>
     159              {child.content}
     160            </p>
    130161            <OpinionReplyCardContentTime>
    131162              {dateConverter(
     
    133164              )}
    134165            </OpinionReplyCardContentTime>
    135             {auth && userLoaded && user.user.id !== child.author.id && (
    136               <>
    137                 <StyledFontAwesomeIcon
    138                   icon={solid("thumbs-up")}
    139                   right={50 + "px"}
    140                   color={
    141                     child.likes.some((e) => e.id === user.user.id)
     166
     167            <div
     168              style={{
     169                display:
     170                  !auth || (auth && loadedUser && user.id !== child.author.id)
     171                    ? "block"
     172                    : "none",
     173              }}
     174            >
     175              <StyledFontAwesomeIcon
     176                icon={solid("thumbs-up")}
     177                right={50 + "px"}
     178                color={
     179                  auth && loadedUser && user
     180                    ? child.votes.some(
     181                        (e) => e.vote === "UPVOTE" && e.user.id === user.id
     182                      )
    142183                      ? "greenyellow"
    143184                      : "darkgrey"
    144                   }
    145                   onClick={() => handleLike(child)}
    146                 />
    147                 <VoteCount right={50 + "px"}>{child.likes.length}</VoteCount>
    148                 <StyledFontAwesomeIcon
    149                   icon={solid("thumbs-down")}
    150                   right={10 + "px"}
    151                   color={
    152                     child.dislikes.some((e) => e.id === user.user.id)
     185                    : "darkgrey"
     186                }
     187                onClick={() => handleLike(child)}
     188              />
     189
     190              <VoteCount right={50 + "px"}>
     191                {child.votes.filter((v) => v.vote === "UPVOTE").length}
     192              </VoteCount>
     193
     194              <StyledFontAwesomeIcon
     195                icon={solid("thumbs-down")}
     196                right={10 + "px"}
     197                color={
     198                  auth && loadedUser && user
     199                    ? child.votes.some(
     200                        (e) => e.vote === "DOWNVOTE" && e.user.id === user.id
     201                      )
    153202                      ? "indianred"
    154203                      : "darkgrey"
    155                   }
    156                   onClick={() => handleDislike(child)}
    157                 />
    158                 <VoteCount right={10 + "px"}>{child.dislikes.length}</VoteCount>
    159                 <StyledFontAwesomeIcon
    160                   icon={solid("reply")}
    161                   right={90 + "px"}
    162                   color="darkgrey"
    163                   onClick={() => handleReply(child)}
    164                 />
    165               </>
    166             )}
     204                    : "darkgrey"
     205                }
     206                onClick={() => handleDislike(child)}
     207              />
     208
     209              <VoteCount right={10 + "px"}>
     210                {child.votes.filter((v) => v.vote === "DOWNVOTE").length}
     211              </VoteCount>
     212
     213              <StyledFontAwesomeIcon
     214                icon={solid("reply")}
     215                right={90 + "px"}
     216                color="darkgrey"
     217                onClick={() => handleReply(child)}
     218              />
     219            </div>
    167220          </OpinionReplyCardContent>
    168221          {child.children.map((childOfChild) =>
     
    187240              <OpinionCard>
    188241                <OpinionCardContent>
    189                   <p>
    190                     <a href="#">{opinion.author.username}</a> напишал
     242                  <p style={{ fontStyle: "italic", marginBottom: "10px" }}>
     243                    <a href={"/user/" + opinion.author.id}>
     244                      {opinion.author.username}
     245                    </a>{" "}
     246                    напишал
    191247                  </p>
    192                   <OpinionCardContentTitle>
    193                     {opinion.title}
    194                   </OpinionCardContentTitle>
    195                   <p>{opinion.content}</p>
     248                  <p style={{ marginBottom: "10px", maxWidth: "90%" }}>
     249                    {opinion.content}
     250                  </p>
    196251                  <OpinionCardContentTime>
    197252                    {dateConverter(
     
    199254                    )}
    200255                  </OpinionCardContentTime>
    201                   {auth && userLoaded && user.user.id !== opinion.author.id && (
    202                     <>
    203                       <StyledFontAwesomeIcon
    204                         icon={solid("thumbs-up")}
    205                         right={50 + "px"}
    206                         color={
    207                           opinion.likes.some((e) => e.id === user.user.id)
     256
     257                  <div
     258                    style={{
     259                      display:
     260                        !auth ||
     261                        (auth && loadedUser && user.id !== opinion.author.id)
     262                          ? "block"
     263                          : "none",
     264                    }}
     265                  >
     266                    <StyledFontAwesomeIcon
     267                      icon={solid("thumbs-up")}
     268                      right={50 + "px"}
     269                      color={
     270                        auth && loadedUser && user
     271                          ? opinion.votes.some(
     272                              (e) =>
     273                                e.vote === "UPVOTE" && e.user.id === user.id
     274                            )
    208275                            ? "greenyellow"
    209276                            : "darkgrey"
    210                         }
    211                         onClick={() => handleLike(opinion)}
    212                       />
    213                       <VoteCount right={50 + "px"}>
    214                         {opinion.likes.length}
    215                       </VoteCount>
    216                       <StyledFontAwesomeIcon
    217                         icon={solid("thumbs-down")}
    218                         right={10 + "px"}
    219                         color={
    220                           opinion.dislikes.some((e) => e.id === user.user.id)
     277                          : "darkgrey"
     278                      }
     279                      onClick={() => handleLike(opinion)}
     280                    />
     281
     282                    <VoteCount right={50 + "px"}>
     283                      {opinion.votes.filter((v) => v.vote === "UPVOTE").length}
     284                    </VoteCount>
     285
     286                    <StyledFontAwesomeIcon
     287                      icon={solid("thumbs-down")}
     288                      right={10 + "px"}
     289                      color={
     290                        auth && loadedUser && user
     291                          ? opinion.votes.some(
     292                              (e) =>
     293                                e.vote === "DOWNVOTE" && e.user.id === user.id
     294                            )
    221295                            ? "indianred"
    222296                            : "darkgrey"
    223                         }
    224                         onClick={() => handleDislike(opinion)}
    225                       />
    226                       <VoteCount right={10 + "px"}>
    227                         {opinion.dislikes.length}
    228                       </VoteCount>
    229                       <StyledFontAwesomeIcon
    230                         icon={solid("reply")}
    231                         right={90 + "px"}
    232                         color="darkgrey"
    233                         onClick={() => handleReply(opinion)}
    234                       />
    235                     </>
    236                   )}
     297                          : "darkgrey"
     298                      }
     299                      onClick={() => handleDislike(opinion)}
     300                    />
     301
     302                    <VoteCount right={10 + "px"}>
     303                      {
     304                        opinion.votes.filter((v) => v.vote === "DOWNVOTE")
     305                          .length
     306                      }
     307                    </VoteCount>
     308
     309                    <StyledFontAwesomeIcon
     310                      icon={solid("reply")}
     311                      right={90 + "px"}
     312                      color="darkgrey"
     313                      onClick={() => handleReply(opinion)}
     314                    />
     315                  </div>
    237316                </OpinionCardContent>
    238317                {opinion.children.map((child) =>
     
    243322          );
    244323        }
     324        return null;
    245325      })}
    246326      {postForModal && (
     
    266346                </label>
    267347              </ModalBody>
     348              <p
     349                style={{ color: "red", marginLeft: "15px", marginTop: "10px" }}
     350              >
     351                {errorMessage}
     352              </p>
    268353              <ModalFooter type="submit">РЕПЛИЦИРАЈ</ModalFooter>
    269354            </form>
  • reactapp/src/Components/Styled/EntityList.style.js

    r8d83180 rc68150f  
    1818export const EntityParam = styled.p`
    1919  position: absolute;
    20   right: 30px;
     20  right: ${(props) => props.right};
    2121  top: 10px;
    2222  font-style: italic;
  • reactapp/src/Components/Styled/Modal.style.js

    r8d83180 rc68150f  
    1818  float: right;
    1919  font-weight: bold;
     20  box-shadow: 2px 1px 10px #aaaaaa;
    2021`;
    2122
  • reactapp/src/Components/Styled/OpinionCard.style.js

    r8d83180 rc68150f  
    1818  }
    1919  position: relative;
     20  overflow-wrap: break-word;
    2021`;
    2122
     
    5556  display: block;
    5657  position: absolute;
     58  height: 20px;
    5759  top: 50%;
    5860  transform: translateY(-50%);
     
    6062  transition: 0.5s;
    6163  &:hover {
    62     color: ${(props) => props.color};
     64    opacity: 0.5;
    6365    cursor: pointer;
    6466  }
  • reactapp/src/Components/SubjectsAccordion.js

    r8d83180 rc68150f  
    2727      <SubjectsAccordionDiv height={height} opacity={opacity}>
    2828        <EntityUl>
    29           {props.content.map((item) => {
    30             let totalPosts = item.threads.length;
    31             return (
    32               <EntityLi key={item.subjectName} bgcolor="cornsilk">
    33                 <a href={"/subject/" + item.subjectId}>{item.subjectName}</a>
    34                 <EntityParam>
    35                   {totalPosts !== 1 ? (
    36                     totalPosts !== 0 ? (
    37                       <span
    38                         style={{
    39                           fontWeight: "normal",
    40                           opacity: totalPosts === 0 ? "0.5" : "1",
    41                         }}
    42                       >
     29          {props.content &&
     30            props.content.map((item) => {
     31              let totalPosts = item.threads.length;
     32              return (
     33                <EntityLi key={item.subjectName} bgcolor="cornsilk">
     34                  <a href={"/subject/" + item.subjectId}>{item.subjectName}</a>
     35                  <EntityParam right="30px">
     36                    {totalPosts !== 1 ? (
     37                      totalPosts !== 0 ? (
    4338                        <span
    4439                          style={{
    45                             fontWeight: "bold",
     40                            fontWeight: "normal",
    4641                            opacity: totalPosts === 0 ? "0.5" : "1",
    4742                          }}
    4843                        >
    49                           {totalPosts}
    50                         </span>{" "}
    51                         мислења
    52                       </span>
    53                     ) : (
    54                       <span
    55                         style={{
    56                           fontWeight: "normal",
    57                           opacity: totalPosts === 0 ? "0.5" : "1",
    58                         }}
    59                       >
     44                          <span
     45                            style={{
     46                              fontWeight: "bold",
     47                              opacity: totalPosts === 0 ? "0.5" : "1",
     48                            }}
     49                          >
     50                            {totalPosts}
     51                          </span>{" "}
     52                          мислења
     53                        </span>
     54                      ) : (
    6055                        <span
    6156                          style={{
    62                             fontWeight: "bold",
     57                            fontWeight: "normal",
    6358                            opacity: totalPosts === 0 ? "0.5" : "1",
    6459                          }}
    6560                        >
    66                           {totalPosts}
    67                         </span>{" "}
    68                         мислења
     61                          <span
     62                            style={{
     63                              fontWeight: "bold",
     64                              opacity: totalPosts === 0 ? "0.5" : "1",
     65                            }}
     66                          >
     67                            {totalPosts}
     68                          </span>{" "}
     69                          мислења
     70                        </span>
     71                      )
     72                    ) : (
     73                      <span style={{ fontWeight: "normal" }}>
     74                        <span style={{ fontWeight: "bold" }}>{totalPosts}</span>{" "}
     75                        мислење
    6976                      </span>
    70                     )
    71                   ) : (
    72                     <span style={{ fontWeight: "normal" }}>
    73                       <span style={{ fontWeight: "bold" }}>{totalPosts}</span>{" "}
    74                       мислење
    75                     </span>
    76                   )}
    77                 </EntityParam>
    78               </EntityLi>
    79             );
    80           })}
     77                    )}
     78                  </EntityParam>
     79                </EntityLi>
     80              );
     81            })}
    8182        </EntityUl>
    8283      </SubjectsAccordionDiv>
  • reactapp/src/Components/UserHeader.js

    r8d83180 rc68150f  
    44import Logout from "./Logout";
    55
    6 function UserHeader({ user, userLoaded }) {
    7   return userLoaded ? (
     6function UserHeader({}) {
     7  const [user, setUser] = useState(null);
     8  const [loadedUser, setLoadedUser] = useState(false);
     9  const [fetchError, setFetchError] = useState(false);
     10
     11  useEffect(() => {
     12    const url = `http://192.168.0.17:8080/secure/currentUser`;
     13
     14    const fetchUser = async () => {
     15      try {
     16        const response = await axios.get(url, { withCredentials: true });
     17        var cyclicGraph = await response.data;
     18        var jsogStructure = JSOG.encode(cyclicGraph);
     19        cyclicGraph = JSOG.decode(jsogStructure);
     20        setUser(cyclicGraph);
     21        setLoadedUser(true);
     22      } catch (error) {
     23        setFetchError(true);
     24      }
     25    };
     26
     27    fetchUser();
     28  }, []);
     29
     30  return loadedUser ? (
    831    <div style={{ float: "left", marginTop: 20, marginLeft: 40 }}>
    932      Најавен/а: <a href="/user_dashboard">{user.username}</a> <Logout />{" "}
Note: See TracChangeset for help on using the changeset viewer.