Changeset 9bf1f8d for reactapp/src/Pages
- Timestamp:
- 01/20/23 22:57:18 (2 years ago)
- Branches:
- main
- Children:
- 8dffe02
- Parents:
- 4abf55a
- Location:
- reactapp/src/Pages
- Files:
-
- 1 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
reactapp/src/Pages/Faculty.js
r4abf55a r9bf1f8d 20 20 const Faculty = () => { 21 21 let params = useParams(); 22 23 const [professors, setProfessors] = useState(null); 24 const [studyProgrammes, setStudyProgrammes] = useState(null); 25 const [professorOpinionCount, setProfessorOpinionCount] = useState(null); 22 26 const [loadedProfessors, setLoadedProfessors] = useState(false); 23 27 const [loadedStudyProgrammes, setLoadedStudyProgrammes] = useState(false); 24 const [ professors, setProfessors] = useState(null);25 const [studyProgrammes, setStudyProgrammes] = useState(null); 28 const [loadedProfessorOpinionCount, setLoadedProfessorOpinionCount] = useState(false); 29 26 30 const [fetchError, setFetchError] = useState(false); 27 31 const [entityType, setEntityType] = useState(0); 28 32 29 33 useEffect(() => { 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}`; 32 33 const fetchDataProfessors = async () => { 34 const fetchProfessors = async () => { 34 35 try { 35 const response = await fetch( urlProfessors);36 const response = await fetch(`http://192.168.1.254:8080/public/professors?facultyId=${params.facultyId}`); 36 37 let cyclicGraph = await response.json(); 37 38 let jsogStructure = JSOG.encode(cyclicGraph); … … 44 45 }; 45 46 46 const fetch DataStudyProgrammes = async () => {47 const fetchStudyProgrammes = async () => { 47 48 try { 48 const response2 = await fetch( urlStudyProgrammes);49 const response2 = await fetch(`http://192.168.1.254:8080/public/study_programmes?facultyId=${params.facultyId}`); 49 50 let cyclicGraph2 = await response2.json(); 50 51 let jsogStructure2 = JSOG.encode(cyclicGraph2); … … 57 58 }; 58 59 59 fetchDataProfessors(); 60 fetchDataStudyProgrammes(); 60 const fetchProfessorOpinionCount = async () => { 61 try { 62 const response3 = await fetch(`http://192.168.1.254:8080/public/faculty/${params.facultyId}/opinionCountForEachProfessor`); 63 let cyclicGraph3 = await response3.json(); 64 let jsogStructure3 = JSOG.encode(cyclicGraph3); 65 cyclicGraph3 = JSOG.decode(jsogStructure3); 66 setProfessorOpinionCount(cyclicGraph3); 67 setLoadedProfessorOpinionCount(true); 68 } catch (error) { 69 setFetchError(true); 70 } 71 } 72 73 fetchProfessors(); 74 fetchStudyProgrammes(); 75 fetchProfessorOpinionCount(); 61 76 }, [params.facultyId]); 62 77 63 return loadedProfessors && professors.length != 0 ? (78 return loadedProfessors && professors.length !== 0 ? ( 64 79 entityType === 0 ? ( 65 80 <> … … 106 121 </div> 107 122 <div key={params.facultyId}> 108 {professors.map((professor) => { 109 let totalPosts = professor.relatedOpinions.length; 110 123 {professors.map((professor, idx) => { 124 let totalPosts = loadedProfessorOpinionCount ? parseInt(professorOpinionCount[idx].split(",")[1]) : 0; 111 125 return ( 112 126 <EntityUl key={professor.professorId}> … … 215 229 key={studyProgramme.studyProgrammeId} 216 230 title={studyProgramme} 217 content={studyProgramme.subjects}218 231 ></SubjectsAccordion> 219 232 ); -
reactapp/src/Pages/Home.js
r4abf55a r9bf1f8d 1 import React, { useContext } from "react"; 2 import { MainWrapper, MainTitle } from "../Components/Styled/Main.style"; 3 import { Outlet } from "react-router-dom"; 4 import Search from "../Components/Search"; 5 import UserHeader from "../Components/UserHeader"; 6 import AuthApi from "../api/AuthApi"; 1 import React, {useEffect, useState} from 'react'; 2 import JSOG from "jsog"; 3 import {OpinionCard, OpinionCardContent, OpinionCardContentTime} from "../Components/Styled/OpinionCard.style"; 4 import LoadingSpinner from "../Components/Styled/LoadingSpinner.style"; 5 import {dateConverter} from "../Util/dateConverter"; 6 import {findParentThread} from "../Util/findParentThread"; 7 import {CurrentPageNav} from "../Components/Styled/Main.style"; 7 8 8 function Home({ user, userLoaded }) { 9 const { auth, setAuth } = useContext(AuthApi); 9 const Home = () => { 10 const [latestOpinions, setLatestOpinions] = useState(null); 11 const [loadedLatestOpinions, setLoadedLatestOpinions] = useState(false); 12 const [latestThreads, setLatestThreads] = useState(null); 13 const [loadedLatestThreads, setLoadedLatestThreads] = useState(false); 10 14 11 return ( 12 <MainWrapper> 13 <style> 14 @import 15 url('https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap'); 16 </style> 17 <style> 18 { 19 "body { background-color: papayawhip;} * {margin: 0; padding: 0; box-sizing: border-box;}" 20 } 21 </style> 22 <a href="/"> 23 <MainTitle>profesori.mk</MainTitle> 24 </a>{" "} 25 <Search /> 26 {auth && <UserHeader />} 27 <div style={{ marginTop: "140px" }}></div> 28 <Outlet /> 29 </MainWrapper> 30 ); 31 } 15 useEffect(() => { 16 Promise.all([fetch(`http://192.168.1.254:8080/public/latest10opinions`), 17 fetch(`http://192.168.1.254:8080/public/latest10threads`)]) 18 .then(([resOpinions, resThreads]) => Promise.all([resOpinions.json(), resThreads.json()])) 19 .then(([dataOpinions, dataThreads]) => { 20 let cyclicGraph1 = dataOpinions; 21 let jsogStructure1 = JSOG.encode(cyclicGraph1); 22 cyclicGraph1 = JSOG.decode(jsogStructure1); 23 setLatestOpinions(cyclicGraph1); 24 setLoadedLatestOpinions(true); 25 26 let cyclicGraph2 = dataThreads; 27 let jsogStructure2 = JSOG.encode(cyclicGraph2); 28 cyclicGraph2 = JSOG.decode(jsogStructure2); 29 setLatestThreads(cyclicGraph2); 30 setLoadedLatestThreads(true); 31 }) 32 33 }, []); 34 35 return ( 36 <> 37 <CurrentPageNav> 38 »{" "} 39 <a href={"/university/1"}> 40 Универзитет „Св. Кирил и Методиј“ 41 </a> 42 </CurrentPageNav> 43 <div style={{display:"grid", gridTemplateColumns:"1fr 1fr", gap:"40px", marginTop:"60px"}}> 44 45 <div id="latestOpinions" style={{gridColumn:"1", paddingLeft:"20px"}}> 46 <h2 style={{fontWeight:"normal", marginBottom:"30px"}}>Последни мислења за <span style={{fontWeight:"bold"}}>професори</span></h2> 47 {loadedLatestOpinions ? latestOpinions.slice(5).map(opinion => { 48 opinion.timePosted = undefined; 49 return <OpinionCard key={opinion.postId}> 50 <OpinionCardContent> 51 <p style={{marginBottom:"10px"}}> 52 во дискусија за{" "} 53 <a href={"/professor/" + opinion.targetProfessor.professorId}> 54 {opinion.targetProfessor.professorName} 55 </a> 56 </p> 57 <p style={{ fontStyle: "italic", marginBottom: "10px" }}> 58 <a href={"/user/" + opinion.author.id}> 59 {opinion.author.username} 60 </a>{" "} 61 напишал 62 </p> 63 <p style={{ marginBottom: "10px", maxWidth: "90%" }}> 64 {opinion.content} 65 </p> 66 {new Date(opinion.timePosted).setMilliseconds(0) === new Date(opinion.timeLastEdited).setMilliseconds(0) ? ( 67 <OpinionCardContentTime> 68 {dateConverter( 69 new Date(opinion.timePosted).toString().slice(4, -43) 70 )} <span style={{fontStyle:"normal",color:"blue"}}>#{opinion.postId}</span> 71 </OpinionCardContentTime> 72 ) : ( 73 <OpinionCardContentTime> 74 {dateConverter( 75 new Date(opinion.timeLastEdited) 76 .toString() 77 .slice(4, -43) 78 )}{" "} <span style={{fontStyle:"normal",color:"blue"}}>#{opinion.postId}</span>{" "} 79 (едитирано од модератор) 80 </OpinionCardContentTime> 81 )} 82 </OpinionCardContent> 83 </OpinionCard> 84 }) : <LoadingSpinner/>} 85 </div> 86 87 <div id="latestThreads" style={{gridColumn:"2", paddingRight:"20px"}}> 88 <h2 style={{fontWeight:"normal", marginBottom:"30px"}}>Последни мислења за <span style={{fontWeight:"bold"}}>предмети</span></h2> 89 {loadedLatestThreads ? latestThreads.slice(5).map(thread => { 90 return <OpinionCard key={thread.postId}> 91 <OpinionCardContent> 92 <p style={{marginBottom:"10px"}}> 93 во дискусија за{" "} 94 <a href={ 95 thread.parent === null 96 ? "/topic/" + thread.postId 97 : "/topic/" + findParentThread(thread).postId 98 } 99 > {thread.targetSubject.subjectName} 100 </a> 101 </p> 102 <p style={{ fontStyle: "italic", marginBottom: "10px" }}> 103 <a href={"/user/" + thread.author.id}> 104 {thread.author.username} 105 </a>{" "} 106 напишал 107 </p> 108 <p style={{ marginBottom: "10px", maxWidth: "90%" }}> 109 {thread.content} 110 </p> 111 {new Date(thread.timePosted).setMilliseconds(0) === new Date(thread.timeLastEdited).setMilliseconds(0) ? ( 112 <OpinionCardContentTime> 113 {dateConverter( 114 new Date(thread.timePosted).toString().slice(4, -43) 115 )} <span style={{fontStyle:"normal",color:"blue"}}>#{thread.postId}</span> 116 </OpinionCardContentTime> 117 ) : ( 118 <OpinionCardContentTime> 119 {dateConverter( 120 new Date(thread.timeLastEdited) 121 .toString() 122 .slice(4, -43) 123 )}{" "} <span style={{fontStyle:"normal",color:"blue"}}>#{thread.postId}</span>{" "} 124 (едитирано од модератор) 125 </OpinionCardContentTime> 126 )} 127 </OpinionCardContent> 128 </OpinionCard> 129 }) : null} 130 </div> 131 </div> 132 </> 133 ); 134 }; 32 135 33 136 export default Home; -
reactapp/src/Pages/Professor.js
r4abf55a r9bf1f8d 32 32 const [professor, setProfessor] = useState(null); 33 33 const [loadedProfessor, setLoadedProfessor] = useState(false); 34 const [relatedOpinions, setRelatedOpinions] = useState(null); 35 const [loadedRelatedOpinions, setLoadedRelatedOpinions] = useState(false); 34 36 35 37 const [postModalDisplay, setPostModalDisplay] = useState("none"); … … 40 42 41 43 useEffect(() => { 42 const url = `http://192.168.0.29:8080/public/professor/${params.professorId}`; 44 Promise.all([fetch(`http://192.168.1.254:8080/public/professor/${params.professorId}`), 45 fetch(`http://192.168.1.254:8080/public/professor/${params.professorId}/relatedOpinions`)]) 46 .then(([resProfessor, resRelatedOpinions]) => Promise.all([resProfessor.json(), resRelatedOpinions.json()])) 47 .then(([dataProfessor, dataRelatedOpinions]) => { 48 let cyclicGraph1 = dataProfessor; 49 let jsogStructure1 = JSOG.encode(cyclicGraph1); 50 cyclicGraph1 = JSOG.decode(jsogStructure1); 51 setProfessor(cyclicGraph1); 52 setLoadedProfessor(true); 43 53 44 const fetchProfessor = async () => { 45 try { 46 const response = await fetch(url); 47 var cyclicGraph = await response.json(); 48 var jsogStructure = JSOG.encode(cyclicGraph); 49 cyclicGraph = JSOG.decode(jsogStructure); 50 setProfessor(cyclicGraph); 51 setLoadedProfessor(true); 52 } catch (error) { 53 setFetchError(true); 54 } 55 }; 54 let cyclicGraph2 = dataRelatedOpinions; 55 let jsogStructure2 = JSOG.encode(cyclicGraph2); 56 cyclicGraph2 = JSOG.decode(jsogStructure2); 57 setRelatedOpinions(cyclicGraph2); 58 setLoadedRelatedOpinions(true); 59 }) 56 60 57 fetchProfessor(); 58 }, [params.professorId]); 61 }, []); 59 62 60 63 const handleAddOpinionButtonClick = () => { … … 77 80 if (!postContent.length < 1) { 78 81 const response = await axios( 79 `http://192.168. 0.29:8080/secure/professor/${params.professorId}/addOpinion`,82 `http://192.168.1.254:8080/secure/professor/${params.professorId}/addOpinion`, 80 83 { 81 84 method: "post", … … 129 132 }} 130 133 > 131 { professor.relatedOpinions.length}{" "}132 { professor.relatedOpinions.length !== 1 ? "мислења" : "мислење"}134 {relatedOpinions.length}{" "} 135 {relatedOpinions.length !== 1 ? "мислења" : "мислење"} 133 136 </h3> 134 137 {auth && ( … … 172 175 173 176 <div className="opinionTree"> 174 <OpinionTree professor={professor} />177 <OpinionTree professor={professor} relatedOpinions={relatedOpinions}/> 175 178 </div> 176 179 <Outlet /> -
reactapp/src/Pages/SearchResults.js
r4abf55a r9bf1f8d 14 14 <SearchResultsWrapper> 15 15 <h3 style={{ marginBottom: "30px" }}>Резултати од пребарувањето:</h3> 16 {location.state.map(( professor) => (17 <SearchResult key={ professor.professorId} margin="10px">18 <SearchResultLink href={ "/professor/" + professor.professorId}>16 {location.state.map((match) => ( 17 <SearchResult key={match.professorId !== undefined ? match.professorId : match.subjectId} margin="10px"> 18 <SearchResultLink href={`/${match.professorId !== undefined ? 'professor': 'subject'}/` + `${match.professorId !== undefined ? match.professorId : match.subjectId}`}> 19 19 <SearchResultText weight="bold" size="medium"> 20 { professor.professorName}20 {match.professorId !== undefined ? match.professorName : match.subjectName} 21 21 </SearchResultText> 22 22 <SearchResultText weight="normal" size="er"> 23 { professor.faculty.facultyName}23 {match.professorId !== undefined ? match.faculty.facultyName : match.studyProgramme.faculty.facultyName} 24 24 </SearchResultText> 25 25 </SearchResultLink> -
reactapp/src/Pages/Subject.js
r4abf55a r9bf1f8d 33 33 let params = useParams(); 34 34 let navigate = useNavigate(); 35 36 35 const { auth, setAuth } = useContext(AuthApi); 36 37 37 const [subject, setSubject] = useState(null); 38 const [loaded, setLoaded] = useState(false); 38 const [loadedSubject, setLoadedSubject] = useState(false); 39 const [threads, setThreads] = useState(null); 40 const [loadedThreads, setLoadedThreads] = useState(false); 39 41 const [fetchError, setFetchError] = useState(false); 42 40 43 var totalTopics = 0; 41 44 var topics = []; … … 47 50 48 51 useEffect(() => { 49 const url = `http://192.168.0.29:8080/public/subject/${params.subjectId}`; 50 51 const fetchData = async () => { 52 try { 53 const response = await fetch(url); 54 let cyclicGraph = await response.json(); 55 let jsogStructure = JSOG.encode(cyclicGraph); 56 cyclicGraph = JSOG.decode(jsogStructure); 57 setSubject(cyclicGraph); 58 setLoaded(true); 59 } catch (error) { 60 setFetchError(true); 61 } 62 }; 63 64 fetchData(); 65 }, [params.subjectId]); 52 Promise.all([fetch(`http://192.168.1.254:8080/public/subject/${params.subjectId}`), 53 fetch(`http://192.168.1.254:8080/public/subject/${params.subjectId}/threads`)]) 54 .then(([resSubject, resThreads]) => Promise.all([resSubject.json(), resThreads.json()])) 55 .then(([dataSubject, dataThreads]) => { 56 let cyclicGraph1 = dataSubject; 57 let jsogStructure1 = JSOG.encode(cyclicGraph1); 58 cyclicGraph1 = JSOG.decode(jsogStructure1); 59 setSubject(cyclicGraph1); 60 setLoadedSubject(true); 61 62 let cyclicGraph2 = dataThreads; 63 let jsogStructure2 = JSOG.encode(cyclicGraph2); 64 cyclicGraph2 = JSOG.decode(jsogStructure2); 65 setThreads(cyclicGraph2); 66 setLoadedThreads(true); 67 }) 68 69 }, []); 66 70 67 71 const handleAddTopicButtonClick = () => { … … 84 88 if (!topicTitle.length < 1 && !topicContent.length < 1) { 85 89 const response = await axios( 86 `http://192.168. 0.29:8080/secure/subject/${params.subjectId}/addThread`,90 `http://192.168.1.254:8080/secure/subject/${params.subjectId}/addThread`, 87 91 { 88 92 method: "post", … … 109 113 }; 110 114 111 return loaded ? (115 return loadedSubject ? ( 112 116 <> 113 117 <CurrentPageNav> … … 151 155 }} 152 156 > 153 { subject.threads.map((thread) => {157 {threads.map((thread) => { 154 158 if (thread.parent === null) { 155 159 totalTopics++; … … 210 214 <EntityUl key={topic.postId}> 211 215 <EntityLi bgcolor="cornsilk"> 212 <a href={"/topic/" + topic.postId}>{topic.title }</a>216 <a href={"/topic/" + topic.postId}>{topic.title.length >= 99 ? topic.title.slice(0,98) + "..." : topic.title}</a> 213 217 <EntityParam right="30px"> 214 218 <span style={{ fontWeight: "normal" }}> -
reactapp/src/Pages/Topic.js
r4abf55a r9bf1f8d 43 43 const [postModalDisplay, setPostModalDisplay] = useState("none"); 44 44 const [postContent, setPostContent] = useState(""); 45 45 46 const [replyModalDisplay, setReplyModalDisplay] = useState("none"); 46 47 const [replyContent, setReplyContent] = useState(""); 47 const [postForModal, setPostForModal] = useState(null); 48 const [postForReplyModal, setPostForReplyModal] = useState(null); 49 50 const [reportModalDisplay, setReportModalDisplay] = useState("none"); 51 const [reportContent, setReportContent] = useState(""); 52 const [postForReportModal, setPostForReportModal] = useState(null); 53 48 54 const [errorMessage, setErrorMessage] = useState(""); 49 55 50 56 useEffect(() => { 51 const url1 = `http://192.168. 0.29:8080/public/thread/${params.topicId}`;52 const url2 = `http://192.168. 0.29:8080/secure/currentUser`;57 const url1 = `http://192.168.1.254:8080/public/thread/${params.topicId}`; 58 const url2 = `http://192.168.1.254:8080/secure/currentUser`; 53 59 54 60 const fetchTopic = async () => { … … 79 85 80 86 fetchTopic().then(fetchUser); 81 }, [ ]);87 }, [loadedThread]); 82 88 83 89 const handleReply = (post) => { 84 90 if (auth) { 85 91 setReplyModalDisplay("block"); 86 setPostForModal(post); 92 setPostForReplyModal(post); 93 document.body.style.overflowY = "hidden"; 94 } else { 95 navigate("/login"); 96 } 97 }; 98 99 const handleReport = (post) => { 100 if (auth) { 101 setReportModalDisplay("block"); 102 setPostForReportModal(post); 87 103 document.body.style.overflowY = "hidden"; 88 104 } else { … … 95 111 }; 96 112 113 const handleReportContentChange = (e) => { 114 e.preventDefault(); 115 setReportContent(e.target.value); 116 }; 117 97 118 const handleReplySubmit = async (e, postId) => { 98 119 e.preventDefault(); … … 100 121 if (!replyContent.length < 1) { 101 122 const response = await axios( 102 `http://192.168. 0.29:8080/secure/subject/${thread.targetSubject.subjectId}/replyToThread/${postId}`,123 `http://192.168.1.254:8080/secure/subject/${thread.targetSubject.subjectId}/replyToThread/${postId}`, 103 124 { 104 125 method: "post", … … 116 137 }; 117 138 139 const handleReportSubmit = async (e, postId) => { 140 e.preventDefault(); 141 142 if (!reportContent.length < 1) { 143 const response = await axios( 144 `http://192.168.1.254:8080/secure/reportThread/${postId}`, 145 { 146 method: "post", 147 data: { 148 description: reportContent, 149 }, 150 withCredentials: true, 151 } 152 ); 153 setErrorMessage(""); 154 window.location.reload(); 155 } else { 156 setErrorMessage("Полето за содржина не смее да биде празно"); 157 } 158 }; 159 118 160 const handleAddOpinionButtonClick = () => { 119 161 if (auth) { … … 129 171 if (!postContent.length < 1) { 130 172 const response = await axios( 131 `http://192.168. 0.29:8080/secure/subject/${thread.targetSubject.subjectId}/replyToThread/${params.topicId}`,173 `http://192.168.1.254:8080/secure/subject/${thread.targetSubject.subjectId}/replyToThread/${params.topicId}`, 132 174 { 133 175 method: "post", … … 147 189 setPostModalDisplay("none"); 148 190 setReplyModalDisplay("none"); 191 setReportModalDisplay("none"); 149 192 document.body.style.overflowY = "auto"; 150 193 }; … … 161 204 ) { 162 205 const response = await axios( 163 `http://192.168. 0.29:8080/secure/upvoteThread/${post.postId}`,206 `http://192.168.1.254:8080/secure/upvoteThread/${post.postId}`, 164 207 { 165 208 method: "get", … … 184 227 ) { 185 228 const response = await axios( 186 `http://192.168. 0.29:8080/secure/downvoteThread/${post.postId}`,229 `http://192.168.1.254:8080/secure/downvoteThread/${post.postId}`, 187 230 { 188 231 method: "get", … … 280 323 color="darkgrey" 281 324 onClick={() => handleReply(child)} 325 /> 326 327 <StyledFontAwesomeIcon 328 icon={solid("flag")} 329 right={130 + "px"} 330 color="darkgrey" 331 onClick={() => handleReport(child)} 282 332 /> 283 333 </div> … … 393 443 > 394 444 <StyledFontAwesomeIcon 445 icon={solid("flag")} 446 right={90 + "px"} 447 color="darkgrey" 448 onClick={() => handleReport(thread)} 449 /> 450 <StyledFontAwesomeIcon 395 451 icon={solid("thumbs-up")} 396 452 right={50 + "px"} … … 517 573 onClick={() => handleReply(directChild)} 518 574 /> 575 576 <StyledFontAwesomeIcon 577 icon={solid("flag")} 578 right={130 + "px"} 579 color="darkgrey" 580 onClick={() => handleReport(directChild)} 581 /> 519 582 </div> 520 583 </OpinionCardContent> … … 525 588 ); 526 589 })} 527 {postFor Modal && (590 {postForReplyModal && ( 528 591 <Modal display={replyModalDisplay}> 529 592 <ModalContent> … … 531 594 <ModalClose onClick={handleModalCloseClick}>×</ModalClose> 532 595 <h3 style={{ marginTop: "5px" }}> 533 Реплика на {postFor Modal.author.username}596 Реплика на {postForReplyModal.author.username} 534 597 </h3> 535 598 </ModalHeader> 536 <form onSubmit={(e) => handleReplySubmit(e, postFor Modal.postId)}>599 <form onSubmit={(e) => handleReplySubmit(e, postForReplyModal.postId)}> 537 600 <ModalBody> 538 601 <label htmlFor="content"> … … 557 620 </Modal> 558 621 )} 622 {postForReportModal && ( 623 <Modal display={reportModalDisplay}> 624 <ModalContent> 625 <ModalHeader> 626 <ModalClose onClick={handleModalCloseClick}>×</ModalClose> 627 <h3 style={{ marginTop: "5px" }}> 628 Пријава за мислење #{postForReportModal.postId} 629 </h3> 630 </ModalHeader> 631 <form onSubmit={(e) => handleReportSubmit(e, postForReportModal.postId)}> 632 <ModalBody> 633 <label htmlFor="content"> 634 <b>Наведете причина</b>: 635 <ModalTextarea 636 id="content" 637 rows="8" 638 cols="100" 639 value={reportContent} 640 onChange={handleReportContentChange} 641 /> 642 </label> 643 </ModalBody> 644 <p 645 style={{ color: "red", marginLeft: "15px", marginTop: "10px" }} 646 > 647 {errorMessage} 648 </p> 649 <ModalFooter type="submit">ПРИЈАВИ</ModalFooter> 650 </form> 651 </ModalContent> 652 </Modal> 653 )} 559 654 </> 560 655 ) : !fetchError && !loadedThread ? ( -
reactapp/src/Pages/University.js
r4abf55a r9bf1f8d 18 18 const University = () => { 19 19 let params = useParams(); 20 const [loaded, setLoaded] = useState(false); 20 21 21 const [faculties, setFaculties] = useState(null); 22 const [loadedFaculties, setLoadedFaculties] = useState(false); 23 24 const [counts, setCounts] = useState(null); 25 const [loadedCounts, setLoadedCounts] = useState(false); 26 22 27 const [fetchError, setFetchError] = useState(false); 23 28 24 29 useEffect(() => { 25 const url = `http://192.168.0.29:8080/public/faculties?universityId=${params.universityId}`; 30 Promise.all([fetch(`http://192.168.1.254:8080/public/faculties?universityId=${params.universityId}`), 31 fetch(`http://192.168.1.254:8080/public/university/${params.universityId}/sectionAndPostCount`)]) 32 .then(([resFaculties, counts]) => Promise.all([resFaculties.json(), counts.json()])) 33 .then(([dataFaculties, dataCounts]) => { 34 let cyclicGraph1 = dataFaculties; 35 let jsogStructure1 = JSOG.encode(cyclicGraph1); 36 cyclicGraph1 = JSOG.decode(jsogStructure1); 37 setFaculties(cyclicGraph1); 38 setLoadedFaculties(true); 26 39 27 const fetchData = async () => { 28 try { 29 const response = await fetch(url); 30 var cyclicGraph = await response.json(); 31 var jsogStructure = JSOG.encode(cyclicGraph); 32 cyclicGraph = JSOG.decode(jsogStructure); 33 setFaculties(cyclicGraph); 34 setLoaded(true); 35 } catch (error) { 36 setFetchError(true); 37 } 38 }; 39 fetchData(); 40 }, [params.universityId]); 40 let cyclicGraph2 = dataCounts; 41 let jsogStructure2 = JSOG.encode(cyclicGraph2); 42 cyclicGraph2 = JSOG.decode(jsogStructure2); 43 setCounts(cyclicGraph2); 44 setLoadedCounts(true); 45 }) 41 46 42 return loaded && !fetchError && faculties.length !== 0 ? ( 47 }, []); 48 49 return loadedFaculties && !fetchError && faculties.length !== 0 ? ( 43 50 <> 44 51 <CurrentPageNav> … … 55 62 </ProfessorCard> 56 63 <div key={params.universityId}> 57 {faculties.map((faculty) => { 58 let totalPosts = 0; 59 let totalSections = 0; 60 faculty.professors.map((professor) => { 61 totalPosts += professor.relatedOpinions.length; 62 totalSections++; 63 }); 64 faculty.studyProgrammes.map((studyProgramme) => { 65 studyProgramme.subjects.map((subject) => { 66 totalPosts += subject.threads.length; 67 totalSections++; 68 }); 69 }); 70 64 {faculties.map((faculty, idx) => { 65 let totalPosts = parseInt(counts[idx].split(",")[2]); 66 let totalSections = parseInt(counts[idx].split(",")[1]); 67 console.log(counts) 71 68 return ( 72 69 <EntityUl key={faculty.facultyId}> … … 104 101 </div> 105 102 </> 106 ) : !fetchError && !loaded ? (103 ) : !fetchError && !loadedFaculties ? ( 107 104 <div> 108 105 <LoadingSpinner style={{ marginTop: "140px" }}/> -
reactapp/src/Pages/UserDashboard.js
r4abf55a r9bf1f8d 27 27 } from "../Components/Styled/Modal.style"; 28 28 import LoadingSpinner from "../Components/Styled/LoadingSpinner.style"; 29 import {findParentThread} from "../Util/findParentThread"; 29 30 30 31 function UserDashboard() { … … 33 34 const [user, setUser] = useState(null); 34 35 const [loadedUser, setLoadedUser] = useState(false); 36 const [authoredPosts, setAuthoredPosts] = useState(null); 37 const [loadedAuthoredPosts, setLoadedAuthoredPosts] = useState(false); 38 35 39 const [fetchError, setFetchError] = useState(false); 36 40 … … 45 49 const [newPostContent, setNewPostContent] = useState(""); 46 50 const [newOpinionTargetProfessorId, setNewOpinionTargetProfessorId] = useState(""); 47 const [newOpinionTargetProfessor, setNewOpinionTargetProfessor] = useState(null);48 const [loadedNewProfessor,setLoadedNewProfessor] = useState(false);49 51 const [newParentPostId, setNewParentPostId] = useState("-1"); 50 52 … … 52 54 const [newParentThreadId,setNewParentThreadId] = useState("-1"); 53 55 const [newTargetSubjectId, setNewTargetSubjectId] = useState(""); 54 const [newTargetSubject, setNewTargetSubject] = useState(null); 55 const [loadedNewSubject, setLoadedNewSubject] = useState(null); 56 56 57 57 58 const [markResolved, setMarkResolved] = useState(false); … … 83 84 }, [reportForModal]); 84 85 85 const[loadingProf, setLoadingProf] = useState(false); 86 const [newOpinionTargetProfessor, setNewOpinionTargetProfessor] = useState(null); 87 const [loadedNewProfessor,setLoadedNewProfessor] = useState(false); 88 const [newProfessorRelatedOpinions, setNewProfessorRelatedOpinions] = useState(null); 89 const [loadedNewProfessorRelatedOpinions, setLoadedNewProfessorRelatedOpinions] = useState(false); 90 const [loadingProf, setLoadingProf] = useState(false); 86 91 87 92 const handleNewTargetProfessorChange = async (e) => { … … 90 95 if (newOpinionTargetProfessorId!=="") { 91 96 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); 97 Promise.all([fetch(`http://192.168.1.254:8080/public/professor/${newOpinionTargetProfessorId}`), 98 fetch(`http://192.168.1.254:8080/public/professor/${newOpinionTargetProfessorId}/relatedOpinions`)]) 99 .then(([resNewOpinionTargetProfessor, resNewProfessorRelatedOpinions]) => Promise.all([resNewOpinionTargetProfessor.json(), resNewProfessorRelatedOpinions.json()])) 100 .then(([dataNewOpinionTargetProfessor, dataNewProfessorRelatedOpinions]) => { 101 let cyclicGraph1 = dataNewOpinionTargetProfessor; 102 var jsogStructure1 = JSOG.encode(cyclicGraph1); 103 cyclicGraph1 = JSOG.decode(jsogStructure1); 104 setNewOpinionTargetProfessor(cyclicGraph1); 105 setLoadedNewProfessor(true); 106 107 let cyclicGraph2 = dataNewProfessorRelatedOpinions; 108 var jsogStructure2 = JSOG.encode(cyclicGraph2); 109 cyclicGraph2 = JSOG.decode(jsogStructure2); 110 setNewProfessorRelatedOpinions(cyclicGraph2); 111 setLoadedNewProfessorRelatedOpinions(true); 112 113 setLoadingProf(false); 114 }) 99 115 } catch (error) { 100 116 setFetchError(true); … … 103 119 } 104 120 105 const[loadingSubj, setLoadingSubj] = useState(false); 121 const [newTargetSubject, setNewTargetSubject] = useState(null); 122 const [loadedNewSubject, setLoadedNewSubject] = useState(false); 123 const [newTargetSubjectThreads, setNewTargetSubjectThreads] = useState(null); 124 const [loadedNewSubjectThreads, setLoadedNewSubjectThreads] = useState(false); 125 const [loadingSubj, setLoadingSubj] = useState(false); 106 126 107 127 const handleNewTargetSubjectChange = async (e) => { … … 110 130 if (newTargetSubjectId!=="") { 111 131 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 } 132 Promise.all([fetch(`http://192.168.1.254:8080/public/subject/${newTargetSubjectId}`), 133 fetch(`http://192.168.1.254:8080/public/subject/${newTargetSubjectId}/threads`)]) 134 .then(([resNewTargetSubject, resNewTargetSubjectThreads]) => Promise.all([resNewTargetSubject.json(), resNewTargetSubjectThreads.json()])) 135 .then(([dataNewTargetSubject, dataNewTargetSubjectThreads]) => { 136 let cyclicGraph1 = dataNewTargetSubject; 137 var jsogStructure1 = JSOG.encode(cyclicGraph1); 138 cyclicGraph1 = JSOG.decode(jsogStructure1); 139 setNewTargetSubject(cyclicGraph1); 140 setLoadedNewSubject(true); 141 142 let cyclicGraph2 = dataNewTargetSubjectThreads; 143 var jsogStructure2 = JSOG.encode(cyclicGraph2); 144 cyclicGraph2 = JSOG.decode(jsogStructure2); 145 setNewTargetSubjectThreads(cyclicGraph2); 146 setLoadedNewSubjectThreads(true); 147 148 setLoadingSubj(false); 149 }) 150 } catch (error) { 151 setFetchError(true); 152 } 122 153 } 123 154 } 124 155 125 156 useEffect(() => { 126 const url1 = `http://192.168.0.29:8080/secure/currentUser`; 127 const url2 = `http://192.168.0.29:8080/secure/getAllPostReports`; 128 129 const fetchUser = async () => { 157 const fetchUser = () => { 130 158 try { 131 159 if(!loadedUser) { 132 const response = await axios.get(url1, {withCredentials: true}); 133 let cyclicGraph = await response.data; 134 var jsogStructure = JSOG.encode(cyclicGraph); 135 cyclicGraph = JSOG.decode(jsogStructure); 136 setUser(cyclicGraph); 137 setLoadedUser(true); 160 Promise.all([axios.get(`http://192.168.1.254:8080/secure/currentUser`, {withCredentials:true}), 161 axios.get(`http://192.168.1.254:8080/secure/currentUser/posts`, {withCredentials:true})]) 162 .then(([resUser, resAuthoredPosts]) => Promise.all([resUser.data, resAuthoredPosts.data])) 163 .then(([dataUser, dataAuthoredPosts]) => { 164 let cyclicGraph1 = dataUser; 165 let jsogStructure1 = JSOG.encode(cyclicGraph1); 166 cyclicGraph1 = JSOG.decode(jsogStructure1); 167 setUser(cyclicGraph1); 168 setLoadedUser(true); 169 170 let cyclicGraph2 = dataAuthoredPosts; 171 let jsogStructure2 = JSOG.encode(cyclicGraph2); 172 cyclicGraph2 = JSOG.decode(jsogStructure2); 173 setAuthoredPosts(cyclicGraph2); 174 setLoadedAuthoredPosts(true); 175 }) 138 176 } 139 if(user.userRole==='MODERATOR') fetchPostReports();177 if(user.userRole==='MODERATOR') fetchPostReports(); 140 178 } catch (error) { 141 179 setFetchError(true); … … 145 183 const fetchPostReports = async () => { 146 184 try { 147 const response = await axios.get( url2, {withCredentials: true});185 const response = await axios.get(`http://192.168.1.254:8080/secure/getAllPostReports`, {withCredentials: true}); 148 186 var cyclicGraph = await response.data; 149 187 var jsogStructure = JSOG.encode(cyclicGraph); … … 160 198 }, [user]); 161 199 162 // useEffect(() => {163 // const timer = setTimeout(() => {164 // if (user === null) window.location.reload(); <---- :-)165 // }, 3000);166 // return () => clearTimeout(timer);167 // }, []);168 169 function findParentThread(post) {170 if (post.parent === null) return post;171 return findParentThread(post.parent);172 }173 174 200 const handleEdit = async (e) => { 175 201 e.preventDefault(); 176 202 try { 177 203 if(reportForModal.post !== null && reportForModal.post.targetProfessor !== undefined) { 178 await axios(`http://192.168. 0.29:8080/secure/updateOpinion/${reportForModal.post.postId}`,204 await axios(`http://192.168.1.254:8080/secure/updateOpinion/${reportForModal.post.postId}`, 179 205 { 180 206 method: "put", … … 186 212 withCredentials: true, 187 213 }) 214 await axios(`http://192.168.1.254:8080/secure/markReportResolved/${reportForModal.postReportId}/${markResolved ? `resolve` : `open`}`,{ 215 method: "get", 216 withCredentials: true 217 }) 188 218 } else if(reportForModal.post !== null && reportForModal.post.targetProfessor === undefined) { 189 await axios(`http://192.168. 0.29:8080/secure/updateThread/${reportForModal.post.postId}`,219 await axios(`http://192.168.1.254:8080/secure/updateThread/${reportForModal.post.postId}`, 190 220 { 191 221 method: "put", … … 199 229 }) 200 230 } 201 await axios(`http://192.168.0.29:8080/secure/markReportResolved/${reportForModal.postReportId}/${markResolved ? `resolve` : `open`}`,{231 await axios(`http://192.168.1.254:8080/secure/markReportResolved/${reportForModal.postReportId}/${markResolved ? `resolve` : `open`}`,{ 202 232 method: "get", 203 233 withCredentials: true 204 234 }) 205 235 } catch (error) { 206 236 setFetchError(true); … … 213 243 try { 214 244 if(reportForModal.post !== null && reportForModal.post.targetProfessor !== undefined) { 215 var response = await axios(`http://192.168. 0.29:8080/secure/updateOpinion/${reportForModal.post.postId}`,245 var response = await axios(`http://192.168.1.254:8080/secure/updateOpinion/${reportForModal.post.postId}`, 216 246 { 217 247 method: "put", … … 223 253 withCredentials: true, 224 254 }) 255 await axios(`http://192.168.1.254:8080/secure/markReportResolved/${reportForModal.postReportId}/${markResolved ? `resolve` : `open`}`,{ 256 method: "get", 257 withCredentials: true 258 }) 225 259 } 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}`,260 var response = await axios(`http://192.168.1.254:8080/secure/updateThread/${reportForModal.post.postId}`, 227 261 { 228 262 method: "put", … … 236 270 }) 237 271 } 238 await axios(`http://192.168. 0.29:8080/secure/markReportResolved/${reportForModal.postReportId}/${markResolved ? `resolve` : `open`}`,{272 await axios(`http://192.168.1.254:8080/secure/markReportResolved/${reportForModal.postReportId}/${markResolved ? `resolve` : `open`}`,{ 239 273 method: "get", 240 274 withCredentials: true … … 251 285 try { 252 286 if(reportForModal.post !== null && reportForModal.post.targetProfessor !== undefined) { 253 await axios(`http://192.168. 0.29:8080/secure/deleteOpinion/${reportForModal.post.postId}`,287 await axios(`http://192.168.1.254:8080/secure/deleteOpinion/${reportForModal.post.postId}`, 254 288 { 255 289 method: "delete", … … 258 292 window.location.reload(); 259 293 } else if(reportForModal.post !== null && reportForModal.post.targetProfessor === undefined) { 260 await axios(`http://192.168. 0.29:8080/secure/deleteThread/${reportForModal.post.postId}`,294 await axios(`http://192.168.1.254:8080/secure/deleteThread/${reportForModal.post.postId}`, 261 295 { 262 296 method: "delete", … … 312 346 })} 313 347 </EntityUl> 314 { user.authoredPosts.length > 0 ? (348 {authoredPosts.length > 0 ? ( 315 349 <h3 style={{ marginBottom: "10px", marginTop:"30px" }}>Ваши мислења:</h3> 316 350 ) : ( 317 351 <h3 style={{ marginBottom: "10px" }}>Немате објавени мислења</h3> 318 352 )} 319 { user.authoredPosts.map((post) => {353 {authoredPosts.map((post) => { 320 354 return ( 321 355 <div key={post.postId}> … … 527 561 во која треба да биде преместено мислењето:</p> 528 562 <div style={{marginTop:"15px"}}> 529 <label>530 563 <ModalInput 531 564 value={newOpinionTargetProfessorId} … … 542 575 <select value={newParentPostId} onChange={e => setNewParentPostId(e.target.value)} style={{width:"280px", display:"block", padding:"5px",marginBottom:"5px", fontFamily: "Roboto Mono, monospace"}}> 543 576 <option value="-1">Постави како самостојно мислење</option> 544 {new OpinionTargetProfessor.relatedOpinions.filter((opinion)=>opinion.postId!==reportForModal.post.postId).map((opinion) => {577 {newProfessorRelatedOpinions.filter((opinion)=>opinion.postId!==reportForModal.post.postId).map((opinion) => { 545 578 return <option key={opinion.postId} value={opinion.postId}>{opinion.postId}</option>}) 546 579 } 547 580 </select>} 548 581 <br/> 549 < input550 type="checkbox"551 defaultChecked={reportForModal.resolved}552 onChange={handleMarkResolved}553 />554 <span style={{marginLeft:"10px", fontWeight:"bold"}}>Означи како разрешено</span>555 </label>582 <label> 583 <input 584 type="checkbox" 585 onChange={handleMarkResolved} 586 /> 587 <span style={{marginLeft:"10px", fontWeight:"bold"}}>Означи како разрешено</span> 588 </label> 556 589 </div> 557 590 {errMsg!=="" && <p style={{color:"red", display:"flex", justifyContent:"space-around"}}>{errMsg}</p>} … … 578 611 <select value={newParentThreadId} onChange={e => setNewParentThreadId(e.target.value)} style={{width:"370px", display:"block", padding:"5px",marginBottom:"5px", fontFamily: "Roboto Mono, monospace"}}> 579 612 <option value="-1">Постави како самостојно мислење (нова тема)</option> 580 {newTargetSubject .threads.filter((thread)=>thread.postId!==reportForModal.post.postId).map((thread) => {613 {newTargetSubjectThreads.filter((thread)=>thread.postId!==reportForModal.post.postId).map((thread) => { 581 614 return <option key={thread.postId} value={thread.postId}>{thread.postId}</option>}) 582 615 }
Note:
See TracChangeset
for help on using the changeset viewer.