Changeset 6221ab6


Ignore:
Timestamp:
08/20/22 21:12:04 (2 years ago)
Author:
unknown <mlviktor23@…>
Branches:
main
Children:
2fcbde4
Parents:
702ca77
Message:

finished add post func. in react, fixed user dashboard details not loading upon login redirect

Files:
15 edited

Legend:

Unmodified
Added
Removed
  • reactapp/src/App.js

    r702ca77 r6221ab6  
    88import AuthApi from "./api/AuthApi";
    99import Cookies from "js-cookie";
     10import axios from "./api/axios";
     11import JSOG from "jsog";
    1012
    1113export default function App() {
    1214  const [auth, setAuth] = useState(false);
     15  const [user, setUser] = useState(null);
     16  const [userLoaded, setUserLoaded] = useState(false);
    1317  const variableAuth = useMemo(() => ({ auth, setAuth }), [auth]);
    1418  const [authLoaded, setAuthLoaded] = useState(false);
     19
     20  const fetchUser = async () => {
     21    try {
     22      const response = await axios.get(
     23        "http://192.168.0.19:8080/secure/currentUser",
     24        { withCredentials: true }
     25      );
     26      var cyclicGraph = await response.data;
     27      var jsogStructure = JSOG.encode(cyclicGraph);
     28      cyclicGraph = JSOG.decode(jsogStructure);
     29      setUser(cyclicGraph);
     30      setUserLoaded(true);
     31    } catch (error) {
     32      console.log("Fetching error", error);
     33    }
     34  };
    1535
    1636  const readCookie = async () => {
     
    1838    if (session) {
    1939      setAuth(true); // go stava true ako postoi takvo cookie (zasto auth=false na sekoe renderiranje)
     40      fetchUser();
    2041    } else {
    2142      setAuth(false);
     
    4364      <BrowserRouter>
    4465        <Routes>
    45           <Route path="/" element={<Home />}>
     66          <Route
     67            path="/"
     68            element={<Home user={user} userLoaded={userLoaded} />}
     69          >
    4670            <Route path="login" element={<Login />}></Route>
    4771            <Route path="professor">
    48               <Route path=":professorId" element={<Professor />} />
     72              <Route
     73                path=":professorId"
     74                element={<Professor user={user} userLoaded={userLoaded} />}
     75              />
    4976            </Route>
    5077            <Route path="search" element={<SearchResults />}></Route>
     
    5380              element={
    5481                <ProtectedRoute auth={auth}>
    55                   <UserDashboard />
     82                  {<UserDashboard user={user} userLoaded={userLoaded} />}
    5683                </ProtectedRoute>
    5784              }
  • reactapp/src/Components/OpinionTree.js

    r702ca77 r6221ab6  
    99  StyledFontAwesomeIcon,
    1010} from "./Styled/OpinionCard.style";
    11 
    1211import { solid } from "@fortawesome/fontawesome-svg-core/import.macro";
    1312import { dateConverter } from "../Util/dateConverter";
    14 
    15 function OpinionTree({ professor }) {
     13import AuthApi from "../api/AuthApi";
     14import { useNavigate } from "react-router-dom";
     15import { useContext, useState } from "react";
     16import {
     17  Modal,
     18  ModalContent,
     19  ModalClose,
     20  ModalHeader,
     21  ModalBody,
     22  ModalTextarea,
     23  ModalFooter,
     24} from "../Components/Styled/Modal.style";
     25import axios from "../api/axios";
     26
     27function OpinionTree({ professor, user, userLoaded }) {
    1628  var renderedOpinionIds = [];
    1729  var postCount; // za da ne go pokazuva ispod postot
     30
     31  let navigate = useNavigate();
     32  const { auth, setAuth } = useContext(AuthApi);
     33
     34  let [replyModalDisplay, setReplyModalDisplay] = useState("none");
     35  const [replyContent, setReplyContent] = useState("");
     36
     37  const handleLike = () => {
     38    if (auth) {
     39      return;
     40    } else {
     41      navigate("/login");
     42    }
     43  };
     44
     45  const handleDislike = () => {
     46    if (auth) {
     47      return;
     48    } else {
     49      navigate("/login");
     50    }
     51  };
     52
     53  const handleReply = () => {
     54    if (auth) {
     55      setReplyModalDisplay("block");
     56    } else {
     57      navigate("/login");
     58    }
     59  };
     60
     61  const handleModalCloseClick = () => {
     62    setReplyModalDisplay("none");
     63  };
     64
     65  const handleContentChange = (e) => {
     66    setReplyContent(e.target.value);
     67  };
     68
     69  const handleReplySubmit = async (e, postId) => {
     70    e.preventDefault();
     71
     72    const response = await axios(
     73      `http://192.168.0.19:8080/secure/professor/${professor.professorId}/replyToOpinion/${postId}`,
     74      {
     75        method: "post",
     76        data: {
     77          content: replyContent,
     78        },
     79        withCredentials: true,
     80      }
     81    );
     82
     83    window.location.reload(false);
     84    //console.log(response);
     85  };
    1886
    1987  function displayChildPosts(child, parentPostAuthorUsername, replyIndent) {
     
    34102              )}
    35103            </OpinionReplyCardContentTime>
    36             <StyledFontAwesomeIcon
    37               icon={solid("thumbs-up")}
    38               right={50 + "px"}
    39               color="greenyellow"
    40             />
    41             <StyledFontAwesomeIcon
    42               icon={solid("thumbs-down")}
    43               right={10 + "px"}
    44               color="indianred"
    45             />
    46             <StyledFontAwesomeIcon
    47               icon={solid("reply")}
    48               right={90 + "px"}
    49               color="black"
    50             />
     104            {auth && userLoaded && user.user.id !== child.author.id && (
     105              <>
     106                <StyledFontAwesomeIcon
     107                  icon={solid("thumbs-up")}
     108                  right={50 + "px"}
     109                  color="greenyellow"
     110                  onClick={handleLike}
     111                />
     112                <StyledFontAwesomeIcon
     113                  icon={solid("thumbs-down")}
     114                  right={10 + "px"}
     115                  color="indianred"
     116                  onClick={handleDislike}
     117                />
     118                <StyledFontAwesomeIcon
     119                  icon={solid("reply")}
     120                  right={90 + "px"}
     121                  color="black"
     122                  onClick={handleReply} //todo
     123                />
     124              </>
     125            )}
    51126          </OpinionReplyCardContent>
    52127          {child.children.map((childOfChild) =>
     
    69144          return (
    70145            <div key={opinion.postId}>
     146              <Modal display={replyModalDisplay}>
     147                <ModalContent>
     148                  <ModalHeader>
     149                    <ModalClose onClick={handleModalCloseClick}>
     150                      &times;
     151                    </ModalClose>
     152                    <h3 style={{ marginTop: "5px" }}>
     153                      Реплика на {opinion.author.username}
     154                    </h3>
     155                  </ModalHeader>
     156                  <form onSubmit={(e) => handleReplySubmit(e, opinion.postId)}>
     157                    <ModalBody>
     158                      <label htmlFor="content">
     159                        <b>Содржина</b>:
     160                        <ModalTextarea
     161                          id="content"
     162                          rows="8"
     163                          cols="100"
     164                          value={replyContent}
     165                          onChange={handleContentChange}
     166                        />
     167                      </label>
     168                    </ModalBody>
     169                    <ModalFooter type="submit">РЕПЛИЦИРАЈ</ModalFooter>
     170                  </form>
     171                </ModalContent>
     172              </Modal>
    71173              <OpinionCard>
    72174                <OpinionCardContent>
     
    83185                    )}
    84186                  </OpinionCardContentTime>
    85                   <StyledFontAwesomeIcon
    86                     icon={solid("thumbs-up")}
    87                     right={50 + "px"}
    88                     color="greenyellow"
    89                   />
    90                   <StyledFontAwesomeIcon
    91                     icon={solid("thumbs-down")}
    92                     right={10 + "px"}
    93                     color="indianred"
    94                   />
    95                   <StyledFontAwesomeIcon
    96                     icon={solid("reply")}
    97                     right={90 + "px"}
    98                     color="black"
    99                   />
     187                  {auth && userLoaded && user.user.id !== opinion.author.id && (
     188                    <>
     189                      <StyledFontAwesomeIcon
     190                        icon={solid("thumbs-up")}
     191                        right={50 + "px"}
     192                        color="greenyellow"
     193                        onClick={handleLike}
     194                      />
     195                      <StyledFontAwesomeIcon
     196                        icon={solid("thumbs-down")}
     197                        right={10 + "px"}
     198                        color="indianred"
     199                        onClick={handleDislike}
     200                      />
     201                      <StyledFontAwesomeIcon
     202                        icon={solid("reply")}
     203                        right={90 + "px"}
     204                        color="black"
     205                        onClick={handleReply}
     206                      />
     207                    </>
     208                  )}
    100209                </OpinionCardContent>
    101210                {opinion.children.map((child) =>
  • reactapp/src/Components/Search.js

    r702ca77 r6221ab6  
    1515
    1616  useEffect(() => {
    17     const url = `http://192.168.0.17:8080/public/professors/nameContains/${transliterate(
     17    const url = `http://192.168.0.19:8080/public/professors/nameContains/${transliterate(
    1818      query
    1919    )}`;
  • reactapp/src/Components/Styled/Modal.style.js

    r702ca77 r6221ab6  
    2727  top: 0;
    2828  width: 100%;
    29   height: 100%;
     29  height: auto;
    3030  overflow: auto;
    3131  background-color: rgb(0, 0, 0);
     
    4747  background-color: #fefefe;
    4848  margin: 15% auto;
    49   padding: 0;
     49  padding: 20px;
    5050  border: 1px solid #888;
    5151  width: 80%;
     
    7272  color: white;
    7373  height: 40px;
    74   margin-bottom: 10px;
     74  margin-bottom: 30px;
    7575`;
    7676
    77 export const ModalFooter = styled.div`
     77export const ModalFooter = styled.button`
    7878  padding: 2px 16px;
    7979  background-color: rgba(0, 102, 204, 1);
     
    8181  color: white;
    8282  height: 40px;
    83   margin-top: 10px;
     83  margin-top: 30px;
    8484  transition: 0.4s;
    8585  &:hover {
     
    8787    cursor: pointer;
    8888  }
     89  font-family: "Roboto Mono", monospace;
     90  width: 100%;
     91  border: 0;
     92  font-size: 18px;
     93  font-weight: bold;
    8994`;
    9095
     
    109114  padding: 12px 16px;
    110115  border: 1px solid #ccc;
     116  resize: none;
    111117`;
  • reactapp/src/Components/Styled/OpinionCard.style.js

    r702ca77 r6221ab6  
    6161  &:hover {
    6262    color: ${(props) => props.color};
     63    cursor: pointer;
    6364  }
    6465`;
  • reactapp/src/Components/UserHeader.js

    r702ca77 r6221ab6  
    44import Logout from "./Logout";
    55
    6 function UserHeader() {
    7   const [user, setUser] = useState(null);
    8   const [loaded, setLoaded] = useState(false);
    9 
    10   useEffect(() => {
    11     const fetchData = async () => {
    12       try {
    13         const response = await axios.get(
    14           "http://192.168.0.17:8080/secure/currentUser",
    15           { withCredentials: true }
    16         );
    17         var cyclicGraph = await response.data;
    18         var jsogStructure = JSOG.encode(cyclicGraph);
    19         cyclicGraph = JSOG.decode(jsogStructure);
    20         setUser(cyclicGraph);
    21         setLoaded(true);
    22       } catch (error) {
    23         console.log("Fetching error", error);
    24       }
    25     };
    26 
    27     fetchData();
    28   }, []);
    29 
    30   return loaded ? (
     6function UserHeader({ user, userLoaded }) {
     7  return userLoaded ? (
    318    <div style={{ float: "left", marginTop: 20, marginLeft: 40 }}>
    329      Најавен/а: <a href="/user_dashboard">{user.username}</a> <Logout />{" "}
  • reactapp/src/Pages/Home.js

    r702ca77 r6221ab6  
    66import AuthApi from "../api/AuthApi";
    77
    8 function Home() {
     8function Home({ user, userLoaded }) {
    99  const { auth, setAuth } = useContext(AuthApi);
    1010
     
    2424      </a>{" "}
    2525      <Search />
    26       {auth && <UserHeader />}
     26      {auth && <UserHeader user={user} userLoaded={userLoaded} />}
    2727      <div style={{ marginTop: "140px" }}></div>
    2828      <Outlet />
  • reactapp/src/Pages/Professor.js

    r702ca77 r6221ab6  
    2222import AuthApi from "../api/AuthApi";
    2323import { useNavigate } from "react-router-dom";
     24import axios from "../api/axios";
    2425
    25 function Professor() {
     26function Professor(user, userLoaded) {
    2627  let params = useParams();
    2728
    2829  let [professor, setProfessor] = useState(null);
    2930  let [loaded, setLoaded] = useState(null);
    30   let [modalDisplay, setModalDisplay] = useState("none");
     31  let [postModalDisplay, setPostModalDisplay] = useState("none");
    3132  let navigate = useNavigate();
    3233  const { auth, setAuth } = useContext(AuthApi);
    33   const [addPostTitle, setAddPostTitle] = useState("");
    34   const [addPostContent, setAddPostContent] = useState("");
     34  const [postTitle, setPostTitle] = useState("");
     35  const [postContent, setPostContent] = useState("");
    3536
    3637  useEffect(() => {
    37     const url = `http://192.168.0.17:8080/public/professor/${params.professorId}`;
     38    const url = `http://192.168.0.19:8080/public/professor/${params.professorId}`;
    3839
    3940    const fetchData = async () => {
     
    5556  const handleAddOpinionButtonClick = () => {
    5657    if (auth) {
    57       setModalDisplay("block");
     58      setPostModalDisplay("block");
    5859    } else {
    5960      navigate("/login");
     
    6263
    6364  const handleModalCloseClick = () => {
    64     setModalDisplay("none");
    65     console.log("here");
     65    setPostModalDisplay("none");
    6666  };
    6767
    68   const handlePostSubmit = () => {};
     68  const handlePostSubmit = async (e) => {
     69    e.preventDefault();
     70
     71    const response = await axios(
     72      `http://192.168.0.19:8080/secure/professor/${professor.professorId}/addOpinion`,
     73      {
     74        method: "post",
     75        data: {
     76          title: postTitle,
     77          content: postContent,
     78        },
     79        withCredentials: true,
     80      }
     81    );
     82
     83    window.location.reload(false);
     84  };
    6985
    7086  const handleTitleChange = (e) => {
    71     setAddPostTitle(e.target.value);
     87    setPostTitle(e.target.value);
    7288  };
    7389
    7490  const handleContentChange = (e) => {
    75     setAddPostContent(e.target.value);
     91    setPostContent(e.target.value);
    7692  };
    7793
     
    100116            {professor.relatedOpinions.length !== 1 ? "мислења" : "мислење"}
    101117          </h3>
    102           <AddOpinionButton onClick={handleAddOpinionButtonClick}>
    103             Објави мислење
    104           </AddOpinionButton>
     118          {auth && (
     119            <AddOpinionButton onClick={handleAddOpinionButtonClick}>
     120              Објави мислење
     121            </AddOpinionButton>
     122          )}
    105123        </div>
    106124
    107         <Modal display={modalDisplay}>
     125        <Modal display={postModalDisplay}>
    108126          <ModalContent>
    109127            <ModalHeader>
     
    113131              </h3>
    114132            </ModalHeader>
    115             <ModalBody>
    116               <form onSubmit={handlePostSubmit}>
    117                 <label for="title">
     133            <form onSubmit={handlePostSubmit}>
     134              <ModalBody>
     135                <label htmlFor="title">
    118136                  <b>Наслов</b>:
    119137                  <ModalInput
    120138                    id="title"
    121139                    type="text"
    122                     value={addPostTitle}
     140                    value={postTitle}
    123141                    onChange={handleTitleChange}
    124142                  />
    125143                </label>
    126                 <label for="content">
     144                <label htmlFor="content">
    127145                  <b>Содржина</b>:
    128146                  <ModalTextarea
     
    130148                    rows="8"
    131149                    cols="100"
    132                     value={addPostContent}
     150                    value={postContent}
    133151                    onChange={handleContentChange}
    134152                  />
    135153                </label>
    136               </form>
    137             </ModalBody>
    138             <ModalFooter>
    139               <h2 style={{ textAlign: "center" }}>ОБЈАВИ</h2>
    140             </ModalFooter>
     154              </ModalBody>
     155              <ModalFooter type="submit">ОБЈАВИ</ModalFooter>
     156            </form>
    141157          </ModalContent>
    142158        </Modal>
    143159
    144160        <div className="opinionTree">
    145           <OpinionTree professor={professor} />
     161          <OpinionTree
     162            professor={professor}
     163            user={user}
     164            userLoaded={userLoaded}
     165          />
    146166        </div>
    147167        <Outlet />
  • reactapp/src/Pages/UserDashboard.js

    r702ca77 r6221ab6  
    1 import React, { useState, useEffect } from "react";
    2 import JSOG from "jsog";
    3 import axios from "../api/axios";
     1import React, { useEffect } from "react";
    42import {
    53  OpinionCard,
     
    1412import { dateConverter } from "../Util/dateConverter";
    1513
    16 function UserDashboard() {
    17   const [user, setUser] = useState(null);
    18   const [loaded, setLoaded] = useState(false);
    19 
     14function UserDashboard({ user, userLoaded }) {
    2015  useEffect(() => {
    21     const fetchData = async () => {
    22       try {
    23         const response = await axios.get(
    24           "http://192.168.0.17:8080/secure/currentUser",
    25           { withCredentials: true }
    26         );
    27         var cyclicGraph = await response.data;
    28         var jsogStructure = JSOG.encode(cyclicGraph);
    29         cyclicGraph = JSOG.decode(jsogStructure);
    30         setUser(cyclicGraph);
    31         setLoaded(true);
    32       } catch (error) {
    33         console.log("Fetching error", error);
    34       }
    35     };
    36 
    37     fetchData();
     16    const timer = setTimeout(() => {
     17      if (user === null) window.location.reload(false);
     18    }, 3000);
     19    return () => clearTimeout(timer);
    3820  }, []);
    3921
    40   return loaded ? (
     22  return userLoaded ? (
    4123    <>
    4224      <h3>Кориснички податоци:</h3>
  • reactapp/src/api/axios.js

    r702ca77 r6221ab6  
    22
    33export default axios.create({
    4   baseURL: "http://192.168.0.17:8080",
     4  baseURL: "http://192.168.0.19:8080",
    55});
  • springapp/src/main/java/mk/profesori/springapp/Controller/PublicController.java

    r702ca77 r6221ab6  
    2323@RestController
    2424@RequestMapping("/public")
    25 @CrossOrigin(origins = { "http://192.168.0.17:3000", "http://192.168.0.24:3000" })
     25@CrossOrigin(origins = { "http://192.168.0.19:3000", "http://192.168.0.24:3000" })
    2626public class PublicController {
    2727
  • springapp/src/main/java/mk/profesori/springapp/Controller/SecureController.java

    r702ca77 r6221ab6  
    2525@RestController
    2626@RequestMapping("/secure")
    27 @CrossOrigin(origins = { "http://192.168.0.17:3000", "http://192.168.0.24:3000" })
     27@CrossOrigin(origins = { "http://192.168.0.19:3000", "http://192.168.0.24:3000" })
    2828public class SecureController {
    2929
  • springapp/src/main/java/mk/profesori/springapp/Security/SecurityConfiguration.java

    r702ca77 r6221ab6  
    3737            @Override
    3838            public void addCorsMappings(CorsRegistry registry) {
    39                 registry.addMapping("/**").allowedOrigins("http://192.168.0.17:3000", "http://192.168.0.24:3000")
     39                registry.addMapping("/**").allowedOrigins("http://192.168.0.19:3000", "http://192.168.0.24:3000")
    4040                        .allowCredentials(true);
    4141            }
  • springapp/src/main/java/mk/profesori/springapp/Service/RegistrationService.java

    r702ca77 r6221ab6  
    4545                String tokenToResend = customUserDetailsService
    4646                        .createToken(userRepository.findByEmail(request.getEmail()).get());
    47                 String link = "http://192.168.0.17:8080/registration/confirm?token=" + tokenToResend;
     47                String link = "http://192.168.0.19:8080/registration/confirm?token=" + tokenToResend;
    4848                emailSender.send(request.getEmail(), emailSender.buildEmail(request.getUsername(), link));
    4949                return tokenToResend;
     
    6666                        UserRole.REGULAR));
    6767
    68         String link = "http://192.168.0.17:8080/registration/confirm?token=" + token;
     68        String link = "http://192.168.0.19:8080/registration/confirm?token=" + token;
    6969
    7070        emailSender.send(request.getEmail(), emailSender.buildEmail(request.getUsername(), link));
  • springapp/src/main/resources/application.properties

    r702ca77 r6221ab6  
    77spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
    88spring.jpa.properties.hibernate.format_sql=true
    9 server.address=192.168.0.17
     9server.address=192.168.0.19
    1010spring.mail.host=192.168.0.24
    1111spring.mail.username=mailuser
Note: See TracChangeset for help on using the changeset viewer.