Changeset c68150f for reactapp/src/Components
- Timestamp:
- 10/27/22 17:35:03 (2 years ago)
- Branches:
- main
- Children:
- 3b6962d
- Parents:
- 8d83180
- Location:
- reactapp/src/Components
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
reactapp/src/Components/OpinionTree.js
r8d83180 rc68150f 3 3 OpinionCardContent, 4 4 OpinionCardContentTime, 5 OpinionCardContentTitle,6 5 OpinionReplyCard, 7 6 OpinionReplyCardContent, … … 14 13 import AuthApi from "../api/AuthApi"; 15 14 import { useNavigate } from "react-router-dom"; 16 import { useContext, useState } from "react"; 15 import { useContext, useState, useEffect } from "react"; 16 import JSOG from "jsog"; 17 17 import { 18 18 Modal, … … 26 26 import axios from "../api/axios"; 27 27 28 function OpinionTree({ professor , user, userLoaded}) {28 function OpinionTree({ professor }) { 29 29 var renderedOpinionIds = []; 30 30 var postCount; // za da ne go pokazuva ispod postot 31 31 32 const { auth, setAuth } = useContext(AuthApi); 32 33 let navigate = useNavigate(); 33 const { auth, setAuth } = useContext(AuthApi); 34 35 let [replyModalDisplay, setReplyModalDisplay] = useState("none"); 34 35 const [replyModalDisplay, setReplyModalDisplay] = useState("none"); 36 36 const [replyContent, setReplyContent] = useState(""); 37 38 37 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 }, []); 39 61 40 62 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 } 56 80 } else { 57 return;81 navigate("/login"); 58 82 } 59 83 }; 60 84 61 85 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 } 78 104 } else { 79 return;105 navigate("/login"); 80 106 } 81 107 }; … … 101 127 e.preventDefault(); 102 128 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 } 116 145 }; 117 146 … … 123 152 <OpinionReplyCard indent={replyIndent + "px"}> 124 153 <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} 128 157 </p> 129 <p>{child.content}</p> 158 <p style={{ marginBottom: "10px", maxWidth: "90%" }}> 159 {child.content} 160 </p> 130 161 <OpinionReplyCardContentTime> 131 162 {dateConverter( … … 133 164 )} 134 165 </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 ) 142 183 ? "greenyellow" 143 184 : "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 ) 153 202 ? "indianred" 154 203 : "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> 167 220 </OpinionReplyCardContent> 168 221 {child.children.map((childOfChild) => … … 187 240 <OpinionCard> 188 241 <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 напишал 191 247 </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> 196 251 <OpinionCardContentTime> 197 252 {dateConverter( … … 199 254 )} 200 255 </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 ) 208 275 ? "greenyellow" 209 276 : "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 ) 221 295 ? "indianred" 222 296 : "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> 237 316 </OpinionCardContent> 238 317 {opinion.children.map((child) => … … 243 322 ); 244 323 } 324 return null; 245 325 })} 246 326 {postForModal && ( … … 266 346 </label> 267 347 </ModalBody> 348 <p 349 style={{ color: "red", marginLeft: "15px", marginTop: "10px" }} 350 > 351 {errorMessage} 352 </p> 268 353 <ModalFooter type="submit">РЕПЛИЦИРАЈ</ModalFooter> 269 354 </form> -
reactapp/src/Components/Styled/EntityList.style.js
r8d83180 rc68150f 18 18 export const EntityParam = styled.p` 19 19 position: absolute; 20 right: 30px;20 right: ${(props) => props.right}; 21 21 top: 10px; 22 22 font-style: italic; -
reactapp/src/Components/Styled/Modal.style.js
r8d83180 rc68150f 18 18 float: right; 19 19 font-weight: bold; 20 box-shadow: 2px 1px 10px #aaaaaa; 20 21 `; 21 22 -
reactapp/src/Components/Styled/OpinionCard.style.js
r8d83180 rc68150f 18 18 } 19 19 position: relative; 20 overflow-wrap: break-word; 20 21 `; 21 22 … … 55 56 display: block; 56 57 position: absolute; 58 height: 20px; 57 59 top: 50%; 58 60 transform: translateY(-50%); … … 60 62 transition: 0.5s; 61 63 &:hover { 62 color: ${(props) => props.color};64 opacity: 0.5; 63 65 cursor: pointer; 64 66 } -
reactapp/src/Components/SubjectsAccordion.js
r8d83180 rc68150f 27 27 <SubjectsAccordionDiv height={height} opacity={opacity}> 28 28 <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 ? ( 43 38 <span 44 39 style={{ 45 fontWeight: " bold",40 fontWeight: "normal", 46 41 opacity: totalPosts === 0 ? "0.5" : "1", 47 42 }} 48 43 > 49 {totalPosts}50 </span>{" "}51 мислења52 </span>53 ) : (54 <span55 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 ) : ( 60 55 <span 61 56 style={{ 62 fontWeight: " bold",57 fontWeight: "normal", 63 58 opacity: totalPosts === 0 ? "0.5" : "1", 64 59 }} 65 60 > 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 мислење 69 76 </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 })} 81 82 </EntityUl> 82 83 </SubjectsAccordionDiv> -
reactapp/src/Components/UserHeader.js
r8d83180 rc68150f 4 4 import Logout from "./Logout"; 5 5 6 function UserHeader({ user, userLoaded }) { 7 return userLoaded ? ( 6 function 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 ? ( 8 31 <div style={{ float: "left", marginTop: 20, marginLeft: 40 }}> 9 32 Најавен/а: <a href="/user_dashboard">{user.username}</a> <Logout />{" "}
Note:
See TracChangeset
for help on using the changeset viewer.