Changes in / [e49d1b6:4abf55a]
- Files:
-
- 14 added
- 1 deleted
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
reactapp/src/App.js
re49d1b6 r4abf55a 14 14 import NotFound from "./Pages/NotFound"; 15 15 import Topic from "./Pages/Topic"; 16 import LoadingSpinner from "./Components/Styled/LoadingSpinner.style"; 16 17 17 18 export default function App() { … … 42 43 return children; 43 44 } else { 44 return < div>се вчитува cookie...</div>;45 return <LoadingSpinner/>; 45 46 } 46 47 }; -
reactapp/src/Components/OpinionTree.js
re49d1b6 r4abf55a 42 42 43 43 useEffect(() => { 44 const url = `http://192.168.0. 19:8080/secure/currentUser`;44 const url = `http://192.168.0.29:8080/secure/currentUser`; 45 45 46 46 const fetchUser = async () => { … … 68 68 ) { 69 69 const response = await axios( 70 `http://192.168.0. 19:8080/secure/upvoteOpinion/${post.postId}`,70 `http://192.168.0.29:8080/secure/upvoteOpinion/${post.postId}`, 71 71 { 72 72 method: "get", … … 74 74 } 75 75 ); 76 window.location.reload( false);76 window.location.reload(); 77 77 } else { 78 78 return; … … 91 91 ) { 92 92 const response = await axios( 93 `http://192.168.0. 19:8080/secure/downvoteOpinion/${post.postId}`,93 `http://192.168.0.29:8080/secure/downvoteOpinion/${post.postId}`, 94 94 { 95 95 method: "get", … … 98 98 ); 99 99 100 window.location.reload( false);100 window.location.reload(); 101 101 } else { 102 102 return; … … 131 131 if (!replyContent.length < 1) { 132 132 const response = await axios( 133 `http://192.168.0. 19:8080/secure/professor/${professor.professorId}/replyToOpinion/${postId}`,133 `http://192.168.0.29:8080/secure/professor/${professor.professorId}/replyToOpinion/${postId}`, 134 134 { 135 135 method: "post", … … 141 141 ); 142 142 setErrorMessage(""); 143 window.location.reload( false);143 window.location.reload(); 144 144 } else { 145 145 setErrorMessage("Полето за содржина не смее да биде празно"); … … 161 161 {child.content} 162 162 </p> 163 { child.timePosted === child.timeLastEdited? (163 {new Date(child.timePosted).setMilliseconds(0) === new Date(child.timeLastEdited).setMilliseconds(0) ? ( 164 164 <OpinionCardContentTime> 165 165 {dateConverter( 166 166 new Date(child.timePosted).toString().slice(4, -43) 167 )} 167 )} <span style={{fontStyle:"normal",color:"blue"}}>#{child.postId}</span> 168 168 </OpinionCardContentTime> 169 169 ) : ( … … 171 171 {dateConverter( 172 172 new Date(child.timeLastEdited).toString().slice(4, -43) 173 )}{" "} 173 )}{" "} <span style={{fontStyle:"normal",color:"blue"}}>#{child.postId}</span>{" "} 174 174 (едитирано од модератор) 175 175 </OpinionCardContentTime> … … 260 260 {opinion.content} 261 261 </p> 262 { opinion.timePosted === opinion.timeLastEdited? (262 {new Date(opinion.timePosted).setMilliseconds(0) === new Date(opinion.timeLastEdited).setMilliseconds(0) ? ( 263 263 <OpinionCardContentTime> 264 264 {dateConverter( 265 265 new Date(opinion.timePosted).toString().slice(4, -43) 266 )} 266 )} <span style={{fontStyle:"normal",color:"blue"}}>#{opinion.postId}</span> 267 267 </OpinionCardContentTime> 268 268 ) : ( … … 272 272 .toString() 273 273 .slice(4, -43) 274 )}{" "} 274 )}{" "} <span style={{fontStyle:"normal",color:"blue"}}>#{opinion.postId}</span>{" "} 275 275 (едитирано од модератор) 276 276 </OpinionCardContentTime> -
reactapp/src/Components/Search.js
re49d1b6 r4abf55a 15 15 16 16 useEffect(() => { 17 const url = `http://192.168.0. 19:8080/public/professors/nameContains/${transliterate(17 const url = `http://192.168.0.29:8080/public/professors/nameContains/${transliterate( 18 18 query 19 19 )}`; -
reactapp/src/Components/Styled/ProfessorCard.style.js
re49d1b6 r4abf55a 2 2 3 3 export const ProfessorCard = styled.div` 4 background-color: cornsilk;5 4 width: auto; 6 5 padding: 10px; -
reactapp/src/Components/UserHeader.js
re49d1b6 r4abf55a 3 3 import axios from "../api/axios"; 4 4 import Logout from "./Logout"; 5 import LoadingSpinner from "./Styled/LoadingSpinner.style"; 5 6 6 7 function UserHeader({}) { … … 10 11 11 12 useEffect(() => { 12 const url = `http://192.168.0. 19:8080/secure/currentUser`;13 const url = `http://192.168.0.29:8080/secure/currentUser`; 13 14 14 15 const fetchUser = async () => { … … 34 35 ) : ( 35 36 <div style={{ float: "left", marginTop: 25, marginLeft: 60 }}> 36 се вчитува...37 <LoadingSpinner/> 37 38 </div> 38 39 ); -
reactapp/src/Pages/Faculty.js
re49d1b6 r4abf55a 16 16 import SubjectsAccordion from "../Components/SubjectsAccordion"; 17 17 import { CurrentPageNav } from "../Components/Styled/Main.style"; 18 import LoadingSpinner from "../Components/Styled/LoadingSpinner.style"; 18 19 19 20 const Faculty = () => { … … 27 28 28 29 useEffect(() => { 29 const urlProfessors = `http://192.168.0. 19:8080/public/professors?facultyId=${params.facultyId}`;30 const urlStudyProgrammes = `http://192.168.0. 19:8080/public/study_programmes?facultyId=${params.facultyId}`;30 const urlProfessors = `http://192.168.0.29:8080/public/professors?facultyId=${params.facultyId}`; 31 const urlStudyProgrammes = `http://192.168.0.29:8080/public/study_programmes?facultyId=${params.facultyId}`; 31 32 32 33 const fetchDataProfessors = async () => { … … 224 225 ) : !fetchError && !loadedProfessors ? ( 225 226 <div> 226 < p style={{ marginTop: "140px" }}>се вчитува...</p>227 <LoadingSpinner style={{ marginTop: "140px" }}/> 227 228 <Outlet /> 228 229 </div> -
reactapp/src/Pages/Login.js
re49d1b6 r4abf55a 17 17 18 18 useEffect(() => { 19 userRef.current.focus();19 if (!auth) userRef.current.focus(); 20 20 }, []); 21 21 -
reactapp/src/Pages/Professor.js
re49d1b6 r4abf55a 24 24 import axios from "../api/axios"; 25 25 import { CurrentPageNav } from "../Components/Styled/Main.style"; 26 import LoadingSpinner from "../Components/Styled/LoadingSpinner.style"; 26 27 27 28 function Professor() { … … 39 40 40 41 useEffect(() => { 41 const url = `http://192.168.0. 19:8080/public/professor/${params.professorId}`;42 const url = `http://192.168.0.29:8080/public/professor/${params.professorId}`; 42 43 43 44 const fetchProfessor = async () => { … … 76 77 if (!postContent.length < 1) { 77 78 const response = await axios( 78 `http://192.168.0. 19:8080/secure/professor/${params.professorId}/addOpinion`,79 `http://192.168.0.29:8080/secure/professor/${params.professorId}/addOpinion`, 79 80 { 80 81 method: "post", … … 86 87 ); 87 88 setErrorMessage(""); 88 window.location.reload( false);89 window.location.reload(); 89 90 } else { 90 91 setErrorMessage("Полето за содржина не смее да биде празно"); … … 111 112 </CurrentPageNav> 112 113 <ProfessorCard> 113 <ProfessorCardName>{professor.professorName} </ProfessorCardName>114 <ProfessorCardName>{professor.professorName} <span style={{opacity:"50%", fontSize:"16px"}}>#{professor.professorId}</span></ProfessorCardName> 114 115 <ProfessorCardSeparator /> 115 116 <div style={{ marginTop: "10px" }}> … … 179 180 return ( 180 181 <div> 181 < p style={{ marginTop: "140px" }}>се вчитува...</p>182 <LoadingSpinner style={{ marginTop: "140px" }}/> 182 183 <Outlet /> 183 184 </div> -
reactapp/src/Pages/Subject.js
re49d1b6 r4abf55a 28 28 } from "../Components/Styled/Modal.style"; 29 29 import axios from "../api/axios"; 30 import LoadingSpinner from "../Components/Styled/LoadingSpinner.style"; 30 31 31 32 const Subject = () => { … … 46 47 47 48 useEffect(() => { 48 const url = `http://192.168.0. 19:8080/public/subject/${params.subjectId}`;49 const url = `http://192.168.0.29:8080/public/subject/${params.subjectId}`; 49 50 50 51 const fetchData = async () => { … … 83 84 if (!topicTitle.length < 1 && !topicContent.length < 1) { 84 85 const response = await axios( 85 `http://192.168.0. 19:8080/secure/subject/${params.subjectId}/addThread`,86 `http://192.168.0.29:8080/secure/subject/${params.subjectId}/addThread`, 86 87 { 87 88 method: "post", … … 94 95 ); 95 96 setErrorMessage(""); 96 window.location.reload( false);97 window.location.reload(); 97 98 } else { 98 99 setErrorMessage("Полињата за наслов и содржина не смеат да бидат празни"); … … 127 128 </CurrentPageNav> 128 129 <ProfessorCard> 129 <ProfessorCardName>{subject.subjectName} </ProfessorCardName>130 <ProfessorCardName>{subject.subjectName} <span style={{opacity:"50%", fontSize:"16px"}}>#{subject.subjectId}</span></ProfessorCardName> 130 131 <ProfessorCardSeparator /> 131 132 <div style={{ marginTop: "10px" }}> … … 204 205 <div key={subject.subjectId}> 205 206 {topics.map((topic) => { 206 var numReplies = topic.children.length; 207 var numReplies = 0; 208 topic.children.map((c)=>numReplies += ++c.children.length); // ++c.children.length -> c + decata na c 207 209 return ( 208 210 <EntityUl key={topic.postId}> … … 268 270 ) : !fetchError ? ( 269 271 <div> 270 < p style={{ marginTop: "140px" }}>се вчитува...</p>272 <LoadingSpinner style={{ marginTop: "140px" }}/> 271 273 <Outlet /> 272 274 </div> -
reactapp/src/Pages/Topic.js
re49d1b6 r4abf55a 28 28 } from "../Components/Styled/Modal.style"; 29 29 import axios from "../api/axios"; 30 import LoadingSpinner from "../Components/Styled/LoadingSpinner.style"; 30 31 31 32 const Topic = () => { … … 48 49 49 50 useEffect(() => { 50 const url1 = `http://192.168.0. 19:8080/public/thread/${params.topicId}`;51 const url2 = `http://192.168.0. 19:8080/secure/currentUser`;51 const url1 = `http://192.168.0.29:8080/public/thread/${params.topicId}`; 52 const url2 = `http://192.168.0.29:8080/secure/currentUser`; 52 53 53 54 const fetchTopic = async () => { … … 99 100 if (!replyContent.length < 1) { 100 101 const response = await axios( 101 `http://192.168.0. 19:8080/secure/subject/${thread.targetSubject.subjectId}/replyToThread/${postId}`,102 `http://192.168.0.29:8080/secure/subject/${thread.targetSubject.subjectId}/replyToThread/${postId}`, 102 103 { 103 104 method: "post", … … 109 110 ); 110 111 setErrorMessage(""); 111 window.location.reload( false);112 window.location.reload(); 112 113 } else { 113 114 setErrorMessage("Полето за содржина не смее да биде празно"); … … 128 129 if (!postContent.length < 1) { 129 130 const response = await axios( 130 `http://192.168.0. 19:8080/secure/subject/${thread.targetSubject.subjectId}/replyToThread/${params.topicId}`,131 `http://192.168.0.29:8080/secure/subject/${thread.targetSubject.subjectId}/replyToThread/${params.topicId}`, 131 132 { 132 133 method: "post", … … 138 139 ); 139 140 setErrorMessage(""); 140 window.location.reload( false);141 window.location.reload(); 141 142 } else { 142 143 setErrorMessage("Полето за содржина не смее да биде празно"); … … 160 161 ) { 161 162 const response = await axios( 162 `http://192.168.0. 19:8080/secure/upvoteThread/${post.postId}`,163 `http://192.168.0.29:8080/secure/upvoteThread/${post.postId}`, 163 164 { 164 165 method: "get", … … 166 167 } 167 168 ); 168 window.location.reload( false);169 window.location.reload(); 169 170 } else { 170 171 return; … … 183 184 ) { 184 185 const response = await axios( 185 `http://192.168.0. 19:8080/secure/downvoteThread/${post.postId}`,186 `http://192.168.0.29:8080/secure/downvoteThread/${post.postId}`, 186 187 { 187 188 method: "get", … … 190 191 ); 191 192 192 window.location.reload( false);193 window.location.reload(); 193 194 } else { 194 195 return; … … 213 214 {child.content} 214 215 </p> 215 { thread.timePosted === thread.timeLastEdited? (216 {new Date(child.timePosted).setMilliseconds(0) === new Date(child.timeLastEdited).setMilliseconds(0) ? ( 216 217 <OpinionCardContentTime> 217 218 {dateConverter( 218 new Date( thread.timePosted).toString().slice(4, -43)219 )} 219 new Date(child.timePosted).toString().slice(4, -43) 220 )} <span style={{fontStyle:"normal",color:"blue"}}>#{child.postId}</span> 220 221 </OpinionCardContentTime> 221 222 ) : ( 222 223 <OpinionCardContentTime> 223 224 {dateConverter( 224 new Date( thread.timeLastEdited).toString().slice(4, -43)225 )}{" "} 225 new Date(child.timeLastEdited).toString().slice(4, -43) 226 )}{" "} <span style={{fontStyle:"normal",color:"blue"}}>#{child.postId}</span>{" "} 226 227 (едитирано од модератор) 227 228 </OpinionCardContentTime> … … 270 271 /> 271 272 272 <VoteCount right={ 50 + "px"}>273 <VoteCount right={10 + "px"}> 273 274 {child.votes.filter((v) => v.vote === "DOWNVOTE").length} 274 275 </VoteCount> … … 324 325 </CurrentPageNav> 325 326 <div style={{ height: "20px", marginBottom: "50px", marginTop: "50px" }}> 326 <h3 style={{ float: "left" }}>{thread.title} </h3>327 <h3 style={{ float: "left" }}>{thread.title} <span style={{opacity:"50%", fontSize:"16px"}}>#{thread.postId}</span></h3> 327 328 {auth && ( 328 329 <AddOpinionButton onClick={handleAddOpinionButtonClick}> … … 369 370 {thread.content} 370 371 </p> 371 { thread.timePosted === thread.timeLastEdited? (372 {new Date(thread.timePosted).setMilliseconds(0) === new Date(thread.timeLastEdited).setMilliseconds(0) ? ( 372 373 <OpinionCardContentTime> 373 374 {dateConverter( 374 375 new Date(thread.timePosted).toString().slice(4, -43) 375 )} 376 )} <span style={{fontStyle:"normal",color:"blue"}}>#{thread.postId}</span> 376 377 </OpinionCardContentTime> 377 378 ) : ( … … 379 380 {dateConverter( 380 381 new Date(thread.timeLastEdited).toString().slice(4, -43) 381 )}{" "} 382 )}{" "} <span style={{fontStyle:"normal",color:"blue"}}>#{thread.postId}</span>{" "} 382 383 (едитирано од модератор) 383 384 </OpinionCardContentTime> … … 444 445 {directChild.content} 445 446 </p> 446 { directChild.timePosted === directChild.timeLastEdited? (447 {new Date(directChild.timePosted).setMilliseconds(0) === new Date(directChild.timeLastEdited).setMilliseconds(0) ? ( 447 448 <OpinionCardContentTime> 448 449 {dateConverter( 449 450 new Date(directChild.timePosted).toString().slice(4, -43) 450 )} 451 )} <span style={{fontStyle:"normal",color:"blue"}}>#{directChild.postId}</span> 451 452 </OpinionCardContentTime> 452 453 ) : ( … … 456 457 .toString() 457 458 .slice(4, -43) 458 )}{" "} 459 )}{" "} <span style={{fontStyle:"normal",color:"blue"}}>#{directChild.postId}</span>{" "} 459 460 (едитирано од модератор) 460 461 </OpinionCardContentTime> … … 559 560 ) : !fetchError && !loadedThread ? ( 560 561 <div> 561 < p style={{ marginTop: "140px" }}>се вчитува...</p>562 <LoadingSpinner style={{ marginTop: "140px" }}/> 562 563 <Outlet /> 563 564 </div> -
reactapp/src/Pages/University.js
re49d1b6 r4abf55a 14 14 } from "../Components/Styled/EntityList.style"; 15 15 import { CurrentPageNav } from "../Components/Styled/Main.style"; 16 import LoadingSpinner from "../Components/Styled/LoadingSpinner.style"; 16 17 17 18 const University = () => { … … 22 23 23 24 useEffect(() => { 24 const url = `http://192.168.0. 19:8080/public/faculties?universityId=${params.universityId}`;25 const url = `http://192.168.0.29:8080/public/faculties?universityId=${params.universityId}`; 25 26 26 27 const fetchData = async () => { … … 105 106 ) : !fetchError && !loaded ? ( 106 107 <div> 107 < p style={{ marginTop: "140px" }}>се вчитува...</p>108 <LoadingSpinner style={{ marginTop: "140px" }}/> 108 109 <Outlet /> 109 110 </div> -
reactapp/src/Pages/UserDashboard.js
re49d1b6 r4abf55a 1 /* eslint-disable no-unused-vars */ 2 // noinspection JSUnresolvedVariable,ES6ConvertVarToLetConst,JSUnresolvedFunction,SpellCheckingInspection,JSUnusedLocalSymbols 3 1 4 import React, { useEffect, useState, useContext } from "react"; 2 5 import { … … 23 26 ModalInput 24 27 } from "../Components/Styled/Modal.style"; 28 import LoadingSpinner from "../Components/Styled/LoadingSpinner.style"; 25 29 26 30 function UserDashboard() { … … 40 44 41 45 const [newPostContent, setNewPostContent] = useState(""); 42 const [newPostTitle, setNewPostTitle] = useState(""); 46 const [newOpinionTargetProfessorId, setNewOpinionTargetProfessorId] = useState(""); 47 const [newOpinionTargetProfessor, setNewOpinionTargetProfessor] = useState(null); 48 const [loadedNewProfessor,setLoadedNewProfessor] = useState(false); 49 const [newParentPostId, setNewParentPostId] = useState("-1"); 50 51 const [newThreadTitle, setNewThreadTitle] = useState(""); 52 const [newParentThreadId,setNewParentThreadId] = useState("-1"); 53 const [newTargetSubjectId, setNewTargetSubjectId] = useState(""); 54 const [newTargetSubject, setNewTargetSubject] = useState(null); 55 const [loadedNewSubject, setLoadedNewSubject] = useState(null); 43 56 44 57 const [markResolved, setMarkResolved] = useState(false); 58 59 const [errMsg, setErrMsg] = useState(""); 45 60 46 61 const handleModalCloseClick = () => { … … 59 74 if (reportForModal.post !== null) { 60 75 setNewPostContent(reportForModal.post.content); 61 if(reportForModal.post.title !== null) setNewPostTitle(reportForModal.post.title); 76 if(reportForModal.post.title !== null) setNewThreadTitle(reportForModal.post.title); 77 if(reportForModal.post.targetProfessor !== undefined) setNewOpinionTargetProfessorId(reportForModal.post.targetProfessor.professorId); //prvicnoto 78 if(reportForModal.post.targetProfessor === undefined) setNewTargetSubjectId(reportForModal.post.targetSubject.subjectId); //prvicnoto 62 79 } 63 80 setReportModalDisplay("block"); … … 66 83 }, [reportForModal]); 67 84 85 const[loadingProf, setLoadingProf] = useState(false); 86 87 const handleNewTargetProfessorChange = async (e) => { 88 setLoadingProf(true); 89 e.preventDefault(); 90 if (newOpinionTargetProfessorId!=="") { 91 try { 92 const response = await axios.get(`http://192.168.0.29:8080/public/professor/${newOpinionTargetProfessorId}`, {withCredentials: true}); 93 let cyclicGraph = await response.data; 94 var jsogStructure = JSOG.encode(cyclicGraph); 95 cyclicGraph = JSOG.decode(jsogStructure); 96 setNewOpinionTargetProfessor(cyclicGraph); 97 setLoadedNewProfessor(true); 98 setLoadingProf(false); 99 } catch (error) { 100 setFetchError(true); 101 } 102 } 103 } 104 105 const[loadingSubj, setLoadingSubj] = useState(false); 106 107 const handleNewTargetSubjectChange = async (e) => { 108 e.preventDefault(); 109 setLoadingSubj(true); 110 if (newTargetSubjectId!=="") { 111 try { 112 const response = await axios.get(`http://192.168.0.29:8080/public/subject/${newTargetSubjectId}`, {withCredentials: true}); 113 let cyclicGraph = await response.data; 114 var jsogStructure = JSOG.encode(cyclicGraph); 115 cyclicGraph = JSOG.decode(jsogStructure); 116 setNewTargetSubject(cyclicGraph); 117 setLoadedNewSubject(true); 118 setLoadingSubj(false); 119 } catch (error) { 120 setFetchError(true); 121 } 122 } 123 } 124 68 125 useEffect(() => { 69 const url1 = `http://192.168.0. 19:8080/secure/currentUser`;70 const url2 = `http://192.168.0. 19:8080/secure/getAllPostReports`;126 const url1 = `http://192.168.0.29:8080/secure/currentUser`; 127 const url2 = `http://192.168.0.29:8080/secure/getAllPostReports`; 71 128 72 129 const fetchUser = async () => { … … 105 162 // useEffect(() => { 106 163 // const timer = setTimeout(() => { 107 // if (user === null) window.location.reload( false); <---- :-)164 // if (user === null) window.location.reload(); <---- :-) 108 165 // }, 3000); 109 166 // return () => clearTimeout(timer); … … 119 176 try { 120 177 if(reportForModal.post !== null && reportForModal.post.targetProfessor !== undefined) { 121 await axios(`http://192.168.0. 19:8080/secure/updateOpinion/${reportForModal.post.postId}`,178 await axios(`http://192.168.0.29:8080/secure/updateOpinion/${reportForModal.post.postId}`, 122 179 { 123 180 method: "put", … … 125 182 newContent: newPostContent, 126 183 newTargetProfessorId: reportForModal.post.targetProfessor.professorId, 184 newParentPostId: reportForModal.post.parent !== null ? reportForModal.post.parent.postId : "-1" 127 185 }, 128 186 withCredentials: true, 129 187 }) 130 window.location.reload(false);131 188 } else if(reportForModal.post !== null && reportForModal.post.targetProfessor === undefined) { 132 await axios(`http://192.168.0. 19:8080/secure/updateThread/${reportForModal.post.postId}`,189 await axios(`http://192.168.0.29:8080/secure/updateThread/${reportForModal.post.postId}`, 133 190 { 134 191 method: "put", 135 192 data: { 136 newTitle: new PostTitle,193 newTitle: newThreadTitle, 137 194 newContent: newPostContent, 138 newTargetSubjectId: reportForModal.post.targetSubject.subjectId 195 newTargetSubjectId: reportForModal.post.targetSubject.subjectId, 196 newParentThreadId: reportForModal.post.parent !== null ? reportForModal.post.parent.postId : "-1" 139 197 }, 140 198 withCredentials: true, 141 199 }) 142 window.location.reload(false); 200 } 201 await axios(`http://192.168.0.29:8080/secure/markReportResolved/${reportForModal.postReportId}/${markResolved ? `resolve` : `open`}`,{ 202 method: "get", 203 withCredentials: true 204 }) 205 } catch (error) { 206 setFetchError(true); 207 } 208 window.location.reload(); 209 } 210 211 const handleRelocate = async (e) => { 212 e.preventDefault(); 213 try { 214 if(reportForModal.post !== null && reportForModal.post.targetProfessor !== undefined) { 215 var response = await axios(`http://192.168.0.29:8080/secure/updateOpinion/${reportForModal.post.postId}`, 216 { 217 method: "put", 218 data: { 219 newContent: reportForModal.post.content, 220 newTargetProfessorId: newOpinionTargetProfessorId, 221 newParentPostId: newParentPostId==="Постави како самостојно мислење" ? "-1" : newParentPostId //:) 222 }, 223 withCredentials: true, 224 }) 225 } else if(reportForModal.post !== null && reportForModal.post.targetProfessor === undefined) { 226 var response = await axios(`http://192.168.0.29:8080/secure/updateThread/${reportForModal.post.postId}`, 227 { 228 method: "put", 229 data: { 230 newTitle: newThreadTitle, 231 newContent: reportForModal.post.content, 232 newTargetSubjectId: newTargetSubjectId, 233 newParentThreadId: newParentThreadId==="Постави како самостојно мислење (нова тема)" ? "-1" : newParentThreadId //:) 234 }, 235 withCredentials: true, 236 }) 237 } 238 await axios(`http://192.168.0.29:8080/secure/markReportResolved/${reportForModal.postReportId}/${markResolved ? `resolve` : `open`}`,{ 239 method: "get", 240 withCredentials: true 241 }) 242 } catch (error) { 243 setFetchError(true); 244 } 245 setErrMsg(response.data); 246 if (response.data==="") window.location.reload(); 247 } 248 249 const handleDelete = async (e) => { 250 e.preventDefault(); 251 try { 252 if(reportForModal.post !== null && reportForModal.post.targetProfessor !== undefined) { 253 await axios(`http://192.168.0.29:8080/secure/deleteOpinion/${reportForModal.post.postId}`, 254 { 255 method: "delete", 256 withCredentials: true, 257 }) 258 window.location.reload(); 259 } else if(reportForModal.post !== null && reportForModal.post.targetProfessor === undefined) { 260 await axios(`http://192.168.0.29:8080/secure/deleteThread/${reportForModal.post.postId}`, 261 { 262 method: "delete", 263 withCredentials: true, 264 }) 143 265 } 144 266 } catch (error) { 145 267 setFetchError(true); 146 268 } 147 } 148 149 const handleDelete = (e) => { 150 e.preventDefault(); 269 window.location.reload(); 151 270 } 152 271 … … 181 300 ) : ( 182 301 <h3>Нема пријавени мислења</h3> 183 ) : loadedUser && user.userRole==='MODERATOR' ? "се вчитува...": ""}302 ) : loadedUser && user.userRole==='MODERATOR' ? <LoadingSpinner/> : ""} 184 303 <EntityUl style={{marginTop:"25px"}}> 185 304 {loadedPostReports && postReports.map((postReport) => { … … 225 344 {dateConverter( 226 345 new Date(post.timePosted).toString().slice(4, -43) 227 )} 346 )} <span style={{fontStyle:"normal",color:"blue"}}>#{post.postId}</span> 228 347 </OpinionCardContentTime> 229 348 </OpinionCardContent> … … 287 406 {dateConverter( 288 407 new Date(reportForModal.post.timePosted).toString().slice(4, -43) 289 )} 408 )} <span style={{fontStyle:"normal",color:"blue"}}>#{reportForModal.post.postId}</span> 290 409 </OpinionCardContentTime> 291 410 </OpinionCardContent> … … 353 472 actionType === 0 ? 354 473 (<form onSubmit={e => handleEdit(e)}> 355 {reportForModal.post.title !== null && <label> 474 {reportForModal.post.title !== null && 475 <label> 356 476 <b>Нов наслов на тема:</b> 357 477 <ModalInput 358 value={new PostTitle}359 onChange={e => setNew PostTitle(e.target.value)}478 value={newThreadTitle} 479 onChange={e => setNewThreadTitle(e.target.value)} 360 480 id="title" 361 481 spellCheck={false} … … 379 499 <input 380 500 type="checkbox" 381 checked={markResolved}382 501 onChange={handleMarkResolved} 383 502 /> … … 403 522 </form>) 404 523 : 405 ("123") 406 : null 524 (reportForModal.post.targetProfessor !== undefined ? 525 (<form onSubmit={e => handleRelocate(e)}> 526 <p style={{color:"black"}}>Внеси <span style={{fontWeight:"bold"}}>ID</span> на секцијата за дискусија (за <span style={{fontWeight:"bold"}}>професор</span>) 527 во која треба да биде преместено мислењето:</p> 528 <div style={{marginTop:"15px"}}> 529 <label> 530 <ModalInput 531 value={newOpinionTargetProfessorId} 532 onChange={e => {e.preventDefault();setNewOpinionTargetProfessorId(e.target.value)}} 533 id="newOpinionTargetProfessorId" 534 spellCheck={false} 535 style={{marginTop:"10px", marginBottom:"10px", width:"90px"}} 536 /> 537 <button onClick={async (e) => {await handleNewTargetProfessorChange(e);}} style={{marginBottom:"10px", padding:"5px", fontFamily: "Roboto Mono, monospace"}}>Зачувај</button> 538 {newOpinionTargetProfessor!==null && !loadingProf ? <p style={{color:"black", marginBottom:"20px", opacity:"50%"}}>Мислењето ќе се премести во секцијата за професорот со <span style={{fontWeight:"bold"}}>ID= 539 {newOpinionTargetProfessor.professorId}</span> (<span style={{fontWeight:"bold"}}>{newOpinionTargetProfessor.professorName}</span>)</p> : loadingProf ? <LoadingSpinner style={{marginBottom:"15px", marginTop:"15px"}}/> : null} 540 {newOpinionTargetProfessor && <p style={{color:"black", marginBottom:"10px"}}>Постави како дете на мислење со ID:</p>} 541 {newOpinionTargetProfessor && 542 <select value={newParentPostId} onChange={e => setNewParentPostId(e.target.value)} style={{width:"280px", display:"block", padding:"5px",marginBottom:"5px", fontFamily: "Roboto Mono, monospace"}}> 543 <option value="-1">Постави како самостојно мислење</option> 544 {newOpinionTargetProfessor.relatedOpinions.filter((opinion)=>opinion.postId!==reportForModal.post.postId).map((opinion) => { 545 return <option key={opinion.postId} value={opinion.postId}>{opinion.postId}</option>}) 546 } 547 </select>} 548 <br/> 549 <input 550 type="checkbox" 551 defaultChecked={reportForModal.resolved} 552 onChange={handleMarkResolved} 553 /> 554 <span style={{marginLeft:"10px", fontWeight:"bold"}}>Означи како разрешено</span> 555 </label> 556 </div> 557 {errMsg!=="" && <p style={{color:"red", display:"flex", justifyContent:"space-around"}}>{errMsg}</p>} 558 <ModalFooter type="submit">ПОТВРДИ</ModalFooter> 559 </form>) : 560 //THREAD CASE 561 (<form onSubmit={e => handleRelocate(e)}> 562 <p style={{color:"black"}}>Внеси <span style={{fontWeight:"bold"}}>ID</span> на секцијата за дискусија (за <span style={{fontWeight:"bold"}}>предмет</span>) 563 во која треба да биде преместено мислењето:</p> 564 <div style={{marginTop:"15px"}}> 565 <label> 566 <ModalInput 567 value={newTargetSubjectId} 568 onChange={e => {e.preventDefault();setNewTargetSubjectId(e.target.value)}} 569 id="newTargetSubjectId" 570 spellCheck={false} 571 style={{marginTop:"10px", marginBottom:"10px", width:"90px"}} 572 /> 573 <button onClick={async (e) => {await handleNewTargetSubjectChange(e);}} style={{marginBottom:"10px", padding:"5px", fontFamily: "Roboto Mono, monospace"}}>Зачувај</button> 574 {newTargetSubject!==null && !loadingSubj ? <p style={{color:"black", marginBottom:"20px", opacity:"50%"}}>Мислењето ќе се премести во секцијата за предметот со <span style={{fontWeight:"bold"}}>ID= 575 {newTargetSubject.subjectId}</span> (<span style={{fontWeight:"bold"}}>{newTargetSubject.subjectName}</span>)</p> : loadingSubj ? <LoadingSpinner style={{marginBottom:"15px", marginTop:"15px"}}/> : null} 576 {newTargetSubject && <p style={{color:"black", marginBottom:"10px"}}>Постави како дете на мислење со ID:</p>} 577 {newTargetSubject && 578 <select value={newParentThreadId} onChange={e => setNewParentThreadId(e.target.value)} style={{width:"370px", display:"block", padding:"5px",marginBottom:"5px", fontFamily: "Roboto Mono, monospace"}}> 579 <option value="-1">Постави како самостојно мислење (нова тема)</option> 580 {newTargetSubject.threads.filter((thread)=>thread.postId!==reportForModal.post.postId).map((thread) => { 581 return <option key={thread.postId} value={thread.postId}>{thread.postId}</option>}) 582 } 583 </select>} 584 {newParentThreadId==="-1" && loadedNewSubject && 585 <> 586 <p style={{marginTop:"10px"}}>Наслов на нова тема:</p> 587 <ModalInput 588 value={newThreadTitle} 589 onChange={e => setNewThreadTitle(e.target.value)} 590 id="titleChangeRelocate" 591 spellCheck={false} 592 style={{marginTop:"10px"}} 593 /> 594 </>} 595 <br/> 596 <input 597 type="checkbox" 598 defaultChecked={reportForModal.resolved} 599 onChange={handleMarkResolved} 600 /> 601 <span style={{marginLeft:"10px", fontWeight:"bold"}}>Означи како разрешено</span> 602 </label> 603 </div> 604 {errMsg!=="" && <p style={{color:"red", display:"flex", justifyContent:"space-around"}}>{errMsg}</p>} 605 <ModalFooter type="submit">ПОТВРДИ</ModalFooter> 606 </form>)) 607 : null 407 608 } 408 609 </ModalBody> … … 412 613 </> 413 614 ) : ( 414 <>се вчитува...</>615 <LoadingSpinner/> 415 616 ); 416 617 } -
reactapp/src/api/axios.js
re49d1b6 r4abf55a 2 2 3 3 export default axios.create({ 4 baseURL: "http://192.168.0. 19:8080",4 baseURL: "http://192.168.0.29:8080", 5 5 }); -
springapp/src/main/java/mk/profesori/springapp/Controller/PublicController.java
re49d1b6 r4abf55a 25 25 @RestController 26 26 @RequestMapping("/public") 27 @CrossOrigin(origins = { "http://192.168.0. 19:3000", "http://192.168.0.39:3000" })27 @CrossOrigin(origins = { "http://192.168.0.29:3000", "http://192.168.0.28:3000" }) 28 28 public class PublicController { 29 29 -
springapp/src/main/java/mk/profesori/springapp/Controller/SecureController.java
re49d1b6 r4abf55a 6 6 import mk.profesori.springapp.Model.UserRole; 7 7 import mk.profesori.springapp.Service.CustomUserDetailsService; 8 import mk.profesori.springapp.Service.DisallowedOperationException; 9 import mk.profesori.springapp.Service.IncompatiblePostId; 8 10 import mk.profesori.springapp.Service.MainService; 9 11 import org.apache.tomcat.websocket.AuthenticationException; … … 18 20 @RestController 19 21 @RequestMapping("/secure") 20 @CrossOrigin(origins = { "http://192.168.0. 19:3000", "http://192.168.0.39:3000" })22 @CrossOrigin(origins = { "http://192.168.0.29:3000", "http://192.168.0.28:3000" }) 21 23 public class SecureController { 22 24 … … 133 135 134 136 @RequestMapping(value = "/updateOpinion/{postId}", method = RequestMethod.PUT) 135 public voidupdateOpinion(@RequestBody ObjectNode objectNode, @PathVariable Long postId,137 public String updateOpinion(@RequestBody ObjectNode objectNode, @PathVariable Long postId, 136 138 @CurrentSecurityContext SecurityContext context) { 137 139 Authentication authentication = context.getAuthentication(); … … 140 142 String newContent = objectNode.get("newContent").asText(); 141 143 Long newTargetProfessorId = objectNode.get("newTargetProfessorId").asLong(); 142 mainService.updateOpinion(newContent, newTargetProfessorId, postId); 143 } 144 Long newParentPostId = objectNode.get("newParentPostId").asLong(); 145 try { 146 mainService.updateOpinion(newContent, newTargetProfessorId, newParentPostId, postId); 147 } catch (IncompatiblePostId | DisallowedOperationException e) { 148 return e.getMessage(); 149 } 150 } 151 152 return null; 144 153 } 145 154 146 155 @RequestMapping(value = "/updateThread/{postId}", method = RequestMethod.PUT) 147 public voidupdateThread(@RequestBody ObjectNode objectNode, @PathVariable Long postId,156 public String updateThread(@RequestBody ObjectNode objectNode, @PathVariable Long postId, 148 157 @CurrentSecurityContext SecurityContext context) { 149 158 Authentication authentication = context.getAuthentication(); … … 153 162 String newContent = objectNode.get("newContent").asText(); 154 163 Long newTargetSubjectId = objectNode.get("newTargetSubjectId").asLong(); 155 156 if (objectNode.has("newParentThreadId")) { 157 Long newParentThreadId = objectNode.get("newParentThreadId").asLong(); 164 Long newParentThreadId = objectNode.get("newParentThreadId").asLong(); 165 try { 158 166 mainService.update_Thread(newTitle, newContent, newTargetSubjectId, newParentThreadId, postId); 159 } else{160 mainService.update_Thread(newTitle, newContent, newTargetSubjectId, null, postId);167 } catch (IncompatiblePostId | DisallowedOperationException e) { 168 return e.getMessage(); 161 169 } 162 170 } 171 172 return null; 163 173 } 164 174 … … 223 233 } 224 234 225 @RequestMapping(value = "/markReportResolved/{postReportId}/ ", method = RequestMethod.GET)235 @RequestMapping(value = "/markReportResolved/{postReportId}/{action}", method = RequestMethod.GET) 226 236 public void markReportResolved(@PathVariable Long postReportId, @PathVariable String action, @CurrentSecurityContext SecurityContext context) { 227 237 Authentication authentication = context.getAuthentication(); 228 if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails currentUser) { 238 if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails currentUser && 239 currentUser.getUserRole().equals(UserRole.MODERATOR)) { 229 240 mainService.markReport(postReportId, action); 230 241 } -
springapp/src/main/java/mk/profesori/springapp/Security/SecurityConfiguration.java
re49d1b6 r4abf55a 37 37 @Override 38 38 public void addCorsMappings(CorsRegistry registry) { 39 registry.addMapping("/**").allowedOrigins("http://192.168.0. 19:3000", "http://192.168.0.39:3000")39 registry.addMapping("/**").allowedOrigins("http://192.168.0.29:3000", "http://192.168.0.28:3000") 40 40 .allowCredentials(true); 41 41 } -
springapp/src/main/java/mk/profesori/springapp/Service/MainService.java
re49d1b6 r4abf55a 141 141 public void addThread(String title, String content, Long subjectId, CustomUserDetails currentUser) { 142 142 Subject targetSubject = subjectRepository.findBySubjectId(subjectId); 143 144 _Thread _threadToAdd = new _Thread(title, content, currentUser, null, null, null, targetSubject); 143 String titleToSet = title.equals("") ? null : title; 144 145 _Thread _threadToAdd = new _Thread(titleToSet, content, currentUser, null, null, null, targetSubject); 145 146 _threadRepository.save(_threadToAdd); 146 147 } … … 199 200 public void delete_Thread(Long postId) {_threadRepository.deleteById(postId);} 200 201 201 public void updateOpinion(String newContent, Long newTargetProfessorId, Long postId) {202 public String updateOpinion(String newContent, Long newTargetProfessorId, Long newParentPostId, Long postId) { 202 203 Opinion opinionToUpdate = opinionRepository.findByPostId(postId); 203 204 … … 205 206 206 207 Professor newTargetProfessor = professorRepository.findByProfessorId(newTargetProfessorId); 207 opinionToUpdate.setTargetProfessor(newTargetProfessor); //opcijava da ja dava samo kaj postovi so parentPost==null 208 opinionToUpdate.setTargetProfessor(newTargetProfessor); 209 210 Opinion newParentOpinion = null; 211 if (newParentPostId != -1) { 212 newParentOpinion = opinionRepository.findByPostId(newParentPostId); 213 if (!newParentOpinion.getTargetProfessor().equals(newTargetProfessor)) 214 throw new IncompatiblePostId("Мислењето не припаѓа во специфицираната секција за дискусија."); 215 if (opinionToUpdate.getChildren().contains(newParentOpinion)) 216 throw new DisallowedOperationException("Мислењето не може да се постави како дете на негово дете (бесконечна рекурзија)"); 217 } 218 opinionToUpdate.setParent(newParentOpinion); 219 208 220 for(Post p : opinionToUpdate.getChildren()) { 209 221 Opinion o = (Opinion) p; … … 212 224 opinionToUpdate.setTimeLastEdited(LocalDateTime.now()); 213 225 opinionRepository.save(opinionToUpdate); 214 } 215 216 public void update_Thread(String newTitle, String newContent, Long newTargetSubjectId, Long newParentThreadId, Long postId) { 226 return null; 227 } 228 229 public String update_Thread(String newTitle, String newContent, Long newTargetSubjectId, Long newParentThreadId, Long postId) { 217 230 _Thread _threadToUpdate = _threadRepository.findByPostId(postId); 218 231 … … 222 235 _threadToUpdate.setTargetSubject(newTargetSubject); 223 236 224 if(newParentThreadId != null) { //samo ako e specificirano225 _Thread newParentThread = _threadRepository.findByPostId(newParentThreadId);226 227 if ( _threadToUpdate.getParent() == null || _threadToUpdate.getParent().getPostId().equals(postId)) {228 _threadToUpdate.setParent(newParentThread);229 }//samo ako e naslovniot post ili directChild230 } else if(_threadToUpdate.getParent() != null) {231 _threadToUpdate.setParent(null);232 }237 _Thread newParentThread = null; 238 if(newParentThreadId != -1) { 239 newParentThread = _threadRepository.findByPostId(newParentThreadId); 240 if (!newParentThread.getTargetSubject().equals(newTargetSubject)) 241 throw new IncompatiblePostId("Мислењето не припаѓа во специфицираната секција за дискусија."); 242 if (_threadToUpdate.getChildren().contains(newParentThread)) 243 throw new DisallowedOperationException("Мислењето не може да се постави како дете на негово дете (бесконечна рекурзија)"); 244 } 245 _threadToUpdate.setParent(newParentThread); 233 246 234 247 if(_threadToUpdate.getParent() == null) { 235 248 _threadToUpdate.setTitle(newTitle); 236 249 } else { 237 _threadToUpdate.setTitle(null);238 250 _threadToUpdate.setTitle(null); 251 } 239 252 240 253 for(Post p : _threadToUpdate.getChildren()) { … … 244 257 _threadToUpdate.setTimeLastEdited(LocalDateTime.now()); 245 258 _threadRepository.save(_threadToUpdate); 259 return null; 246 260 } 247 261 … … 280 294 if (action.equals("resolve")) report.setResolved(true); 281 295 else if (action.equals("open")) report.setResolved(false); 296 postReportRepository.save(report); 282 297 } 283 298 -
springapp/src/main/java/mk/profesori/springapp/Service/RegistrationService.java
re49d1b6 r4abf55a 45 45 String tokenToResend = customUserDetailsService 46 46 .createToken(userRepository.findByEmail(request.getEmail()).get()); 47 String link = "http://192.168.0. 19:8080/registration/confirm?token=" + tokenToResend;47 String link = "http://192.168.0.29:8080/registration/confirm?token=" + tokenToResend; 48 48 emailSender.send(request.getEmail(), emailSender.buildEmail(request.getUsername(), link)); 49 49 return tokenToResend; … … 66 66 UserRole.REGULAR)); 67 67 68 String link = "http://192.168.0. 19:8080/registration/confirm?token=" + token;68 String link = "http://192.168.0.29:8080/registration/confirm?token=" + token; 69 69 70 70 emailSender.send(request.getEmail(), emailSender.buildEmail(request.getUsername(), link)); -
springapp/src/main/resources/application.properties
re49d1b6 r4abf55a 1 spring.datasource.url=jdbc:postgresql://localhost:5432/profesori.mk 2 spring.datasource.connectionProperties=useUnicode=true;characterEncoding=utf-8; 1 spring.datasource.url=jdbc:postgresql://localhost:5432/profesorimk 3 2 spring.datasource.username=postgres 4 spring.datasource.password= 1win73373 spring.datasource.password=baz@228 5 4 spring.jpa.hibernate.ddl-auto=update 6 5 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect 7 6 spring.jpa.show-sql=false 8 7 spring.jpa.properties.hibernate.format_sql=true 9 server.address=192.168.0. 198 server.address=192.168.0.29 10 9 spring.mail.host=localhost 11 10 spring.mail.username=mailuser
Note:
See TracChangeset
for help on using the changeset viewer.