Changeset c68150f for reactapp/src/Pages
- Timestamp:
- 10/27/22 17:35:03 (2 years ago)
- Branches:
- main
- Children:
- 3b6962d
- Parents:
- 8d83180
- Location:
- reactapp/src/Pages
- Files:
-
- 1 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
reactapp/src/Pages/Faculty.js
r8d83180 rc68150f 60 60 }, [params.facultyId]); 61 61 62 return loadedProfessors ? (62 return loadedProfessors && professors.length != 0 ? ( 63 63 entityType === 0 ? ( 64 64 <> … … 114 114 {professor.professorName} 115 115 </a> 116 <EntityParam >116 <EntityParam right="30px"> 117 117 {totalPosts !== 1 ? ( 118 118 totalPosts !== 0 ? ( … … 168 168 <> 169 169 <CurrentPageNav> 170 »{" "} 170 171 <a 171 172 href={ … … 175 176 {professors[0].faculty.university.universityName} 176 177 </a>{" "} 177 /<a href="#">{professors[0].faculty.facultyName}</a>178 » <a href="#">{professors[0].faculty.facultyName}</a> 178 179 </CurrentPageNav> 179 180 <ProfessorCard> … … 221 222 ) 222 223 ) 223 ) : !fetchError ? (224 ) : !fetchError && !loadedProfessors ? ( 224 225 <div> 225 226 <p style={{ marginTop: "140px" }}>се вчитува...</p> -
reactapp/src/Pages/Home.js
r8d83180 rc68150f 24 24 </a>{" "} 25 25 <Search /> 26 {auth && <UserHeader user={user} userLoaded={userLoaded}/>}26 {auth && <UserHeader />} 27 27 <div style={{ marginTop: "140px" }}></div> 28 28 <Outlet /> -
reactapp/src/Pages/Login.js
r8d83180 rc68150f 35 35 if (!response.request.responseURL.includes("error")) { 36 36 // ako NE redirektira na /login?error 37 Cookies.set("JSESSIONID", response.data.sessionId); 37 var in30Minutes = 1 / 48; 38 Cookies.set("JSESSIONID", response.data.sessionId, { 39 expires: in30Minutes, 40 }); 38 41 setAuth(true); 39 42 setErrMsg(""); -
reactapp/src/Pages/Professor.js
r8d83180 rc68150f 25 25 import { CurrentPageNav } from "../Components/Styled/Main.style"; 26 26 27 function Professor( user, userLoaded) {27 function Professor() { 28 28 let params = useParams(); 29 let navigate = useNavigate(); 29 30 30 let [professor, setProfessor] = useState(null);31 let [loaded, setLoaded] = useState(null);32 let [postModalDisplay, setPostModalDisplay] = useState("none"); 33 let navigate = useNavigate();31 const [professor, setProfessor] = useState(null); 32 const [loadedProfessor, setLoadedProfessor] = useState(false); 33 34 const [postModalDisplay, setPostModalDisplay] = useState("none"); 34 35 const { auth, setAuth } = useContext(AuthApi); 35 const [postTitle, setPostTitle] = useState("");36 36 const [postContent, setPostContent] = useState(""); 37 37 const [fetchError, setFetchError] = useState(false); 38 const [errorMessage, setErrorMessage] = useState(""); 38 39 39 40 useEffect(() => { 40 41 const url = `http://192.168.0.17:8080/public/professor/${params.professorId}`; 41 42 42 const fetch Data= async () => {43 const fetchProfessor = async () => { 43 44 try { 44 45 const response = await fetch(url); … … 47 48 cyclicGraph = JSOG.decode(jsogStructure); 48 49 setProfessor(cyclicGraph); 49 setLoaded (true);50 setLoadedProfessor(true); 50 51 } catch (error) { 51 52 setFetchError(true); … … 53 54 }; 54 55 55 fetch Data();56 fetchProfessor(); 56 57 }, [params.professorId]); 57 58 … … 71 72 e.preventDefault(); 72 73 73 const response = await axios( 74 `http://192.168.0.17:8080/secure/professor/${professor.professorId}/addOpinion`, 75 { 76 method: "post", 77 data: { 78 title: postTitle, 79 content: postContent, 80 }, 81 withCredentials: true, 82 } 83 ); 84 85 window.location.reload(false); 86 }; 87 88 const handleTitleChange = (e) => { 89 setPostTitle(e.target.value); 74 if (!postContent.length < 1) { 75 const response = await axios( 76 `http://192.168.0.17:8080/secure/professor/${params.professorId}/addOpinion`, 77 { 78 method: "post", 79 data: { 80 content: postContent, 81 }, 82 withCredentials: true, 83 } 84 ); 85 setErrorMessage(""); 86 window.location.reload(false); 87 } else { 88 setErrorMessage("Полето за содржина не смее да биде празно"); 89 } 90 90 }; 91 91 … … 94 94 }; 95 95 96 if (loaded ) {96 if (loadedProfessor) { 97 97 return ( 98 98 <div> … … 120 120 </div> 121 121 </ProfessorCard> 122 <div style={{ height: "20px", marginBottom: " 30px" }}>122 <div style={{ height: "20px", marginBottom: "50px" }}> 123 123 <h3 124 124 style={{ … … 146 146 <form onSubmit={handlePostSubmit}> 147 147 <ModalBody> 148 <label htmlFor="title">149 <b>Наслов</b>:150 <ModalInput151 id="title"152 type="text"153 value={postTitle}154 onChange={handleTitleChange}155 />156 </label>157 148 <label htmlFor="content"> 158 149 <b>Содржина</b>: … … 166 157 </label> 167 158 </ModalBody> 159 <p 160 style={{ color: "red", marginLeft: "15px", marginTop: "10px" }} 161 > 162 {errorMessage} 163 </p> 168 164 <ModalFooter type="submit">ОБЈАВИ</ModalFooter> 169 165 </form> … … 172 168 173 169 <div className="opinionTree"> 174 <OpinionTree 175 professor={professor} 176 user={user} 177 userLoaded={userLoaded} 178 /> 170 <OpinionTree professor={professor} /> 179 171 </div> 180 172 <Outlet /> -
reactapp/src/Pages/Registration.js
r8d83180 rc68150f 1 import React, { useRef, useState, useEffect } from "react";1 import React, { useRef, useState, useEffect, useContext } from "react"; 2 2 import axios from "../api/axios"; 3 3 import { … … 7 7 RequiredAsterisk, 8 8 } from "../Components/Styled/Login.style"; 9 import { Navigate } from "react-router-dom"; 10 import AuthApi from "../api/AuthApi"; 9 11 const REGISTRATION_URL = "/registration"; 10 12 11 13 const Registration = () => { 14 const { auth, setAuth } = useContext(AuthApi); 12 15 const userRef = useRef(); 13 16 const errRef = useRef(); … … 50 53 useState(0); 51 54 52 return registrationSuccessful === false ? ( 55 return auth ? ( 56 <Navigate to="/user_dashboard" /> 57 ) : registrationSuccessful === false ? ( 53 58 <div 54 59 style={{ -
reactapp/src/Pages/Subject.js
r8d83180 rc68150f 1 import React from "react"; 2 import { useParams } from "react-router-dom"; 1 import React, { useState, useEffect, useContext } from "react"; 2 import { useNavigate, useParams } from "react-router-dom"; 3 import JSOG from "jsog"; 4 import { Outlet } from "react-router-dom"; 5 import { CurrentPageNav } from "../Components/Styled/Main.style"; 6 import { 7 ProfessorCard, 8 ProfessorCardDetails, 9 ProfessorCardName, 10 ProfessorCardSeparator, 11 } from "../Components/Styled/ProfessorCard.style"; 12 import AuthApi from "../api/AuthApi"; 13 import { AddOpinionButton } from "../Components/Styled/Modal.style"; 14 import { 15 EntityLi, 16 EntityUl, 17 EntityParam, 18 } from "../Components/Styled/EntityList.style"; 19 import { 20 Modal, 21 ModalBody, 22 ModalClose, 23 ModalContent, 24 ModalFooter, 25 ModalHeader, 26 ModalInput, 27 ModalTextarea, 28 } from "../Components/Styled/Modal.style"; 29 import axios from "../api/axios"; 3 30 4 31 const Subject = () => { 5 32 let params = useParams(); 6 return <div>Subject {params.subjectId}</div>; 33 let navigate = useNavigate(); 34 35 const { auth, setAuth } = useContext(AuthApi); 36 const [subject, setSubject] = useState(null); 37 const [loaded, setLoaded] = useState(false); 38 const [fetchError, setFetchError] = useState(false); 39 var totalTopics = 0; 40 var topics = []; 41 42 const [topicModalDisplay, setTopicModalDisplay] = useState("none"); 43 const [topicTitle, setTopicTitle] = useState(""); 44 const [topicContent, setTopicContent] = useState(""); 45 const [errorMessage, setErrorMessage] = useState(""); 46 47 useEffect(() => { 48 const url = `http://192.168.0.17:8080/public/subject/${params.subjectId}`; 49 50 const fetchData = async () => { 51 try { 52 const response = await fetch(url); 53 let cyclicGraph = await response.json(); 54 let jsogStructure = JSOG.encode(cyclicGraph); 55 cyclicGraph = JSOG.decode(jsogStructure); 56 setSubject(cyclicGraph); 57 setLoaded(true); 58 } catch (error) { 59 setFetchError(true); 60 } 61 }; 62 63 fetchData(); 64 }, [params.subjectId]); 65 66 const handleAddTopicButtonClick = () => { 67 if (auth) { 68 setTopicModalDisplay("block"); 69 } else { 70 navigate("/login"); 71 } 72 }; 73 74 const handleModalCloseClick = () => { 75 setTopicModalDisplay("none"); 76 }; 77 78 const handleTopicSubmit = async (e) => { 79 e.preventDefault(); 80 81 if (!topicTitle.length < 1 && !topicContent.length < 1) { 82 const response = await axios( 83 `http://192.168.0.17:8080/secure/subject/${params.subjectId}/addThread`, 84 { 85 method: "post", 86 data: { 87 title: topicTitle, 88 content: topicContent, 89 }, 90 withCredentials: true, 91 } 92 ); 93 setErrorMessage(""); 94 window.location.reload(false); 95 } else { 96 setErrorMessage("Полињата за наслов и содржина не смеат да бидат празни"); 97 } 98 }; 99 100 const handleContentChange = (e) => { 101 setTopicContent(e.target.value); 102 }; 103 104 const handleTitleChange = (e) => { 105 setTopicTitle(e.target.value); 106 }; 107 108 return loaded ? ( 109 <> 110 <CurrentPageNav> 111 »{" "} 112 <a 113 href={ 114 "/university/" + 115 subject.studyProgramme.faculty.university.universityId 116 } 117 > 118 {subject.studyProgramme.faculty.university.universityName} 119 </a>{" "} 120 »{" "} 121 <a href={"/faculty/" + subject.studyProgramme.faculty.facultyId}> 122 {subject.studyProgramme.faculty.facultyName} 123 </a>{" "} 124 » <a href="#">{subject.subjectName}</a> 125 </CurrentPageNav> 126 <ProfessorCard> 127 <ProfessorCardName>{subject.subjectName}</ProfessorCardName> 128 <ProfessorCardSeparator /> 129 <div style={{ marginTop: "10px" }}> 130 <ProfessorCardDetails fontSize="20px"> 131 {subject.studyProgramme.studyProgrammeName} ( 132 {subject.studyProgramme.cycle} 133 {"."} 134 {"циклус"}) 135 </ProfessorCardDetails> 136 <ProfessorCardDetails fontSize="20px"> 137 {subject.studyProgramme.faculty.facultyName} 138 </ProfessorCardDetails> 139 <ProfessorCardDetails fontSize="15px"> 140 {subject.studyProgramme.faculty.university.universityName} 141 </ProfessorCardDetails> 142 </div> 143 </ProfessorCard> 144 <div style={{ height: "20px", marginBottom: "50px" }}> 145 <h3 146 style={{ 147 float: "left", 148 }} 149 > 150 {subject.threads.map((thread) => { 151 if (thread.parent === null) { 152 totalTopics++; 153 topics.push(thread); 154 } 155 })} 156 {totalTopics} {totalTopics !== 1 ? "теми" : "тема"} 157 </h3> 158 {auth && ( 159 <AddOpinionButton onClick={handleAddTopicButtonClick}> 160 Отвори тема 161 </AddOpinionButton> 162 )} 163 </div> 164 <Modal display={topicModalDisplay}> 165 <ModalContent> 166 <ModalHeader> 167 <ModalClose onClick={handleModalCloseClick}>×</ModalClose> 168 <h3 style={{ marginTop: "5px" }}> 169 Тема во врска со {subject.subjectName} 170 </h3> 171 </ModalHeader> 172 <form onSubmit={handleTopicSubmit}> 173 <ModalBody> 174 <label htmlFor="title"> 175 <b>Наслов</b>: 176 <ModalInput 177 id="title" 178 value={topicTitle} 179 onChange={handleTitleChange} 180 /> 181 </label> 182 <label htmlFor="content"> 183 <b>Содржина</b>: 184 <ModalTextarea 185 id="content" 186 rows="8" 187 cols="100" 188 value={topicContent} 189 onChange={handleContentChange} 190 /> 191 </label> 192 </ModalBody> 193 <p style={{ color: "red", marginLeft: "15px", marginTop: "10px" }}> 194 {errorMessage} 195 </p> 196 <ModalFooter type="submit">ОБЈАВИ</ModalFooter> 197 </form> 198 </ModalContent> 199 </Modal> 200 <div key={subject.subjectId}> 201 {topics.map((topic) => { 202 var numReplies = topic.children.length; 203 return ( 204 <EntityUl key={topic.postId}> 205 <EntityLi bgcolor="cornsilk"> 206 <a href={"/topic/" + topic.postId}>{topic.title}</a> 207 <EntityParam right="30px"> 208 <span style={{ fontWeight: "normal" }}> 209 отворил:{" "} 210 <a href={"/user/" + topic.author.id}> 211 {topic.author.username} 212 </a> 213 </span> 214 <span style={{ fontStyle: "normal" }}>,</span>{" "} 215 {numReplies !== 1 ? ( 216 numReplies !== 0 ? ( 217 <span 218 style={{ 219 fontWeight: "normal", 220 opacity: numReplies === 0 ? "0.5" : "1", 221 }} 222 > 223 <span 224 style={{ 225 fontWeight: "bold", 226 opacity: numReplies === 0 ? "0.5" : "1", 227 }} 228 > 229 {numReplies} 230 </span>{" "} 231 реплики 232 </span> 233 ) : ( 234 <span 235 style={{ 236 fontWeight: "normal", 237 opacity: numReplies === 0 ? "0.5" : "1", 238 }} 239 > 240 <span 241 style={{ 242 fontWeight: "bold", 243 opacity: numReplies === 0 ? "0.5" : "1", 244 }} 245 > 246 {numReplies} 247 </span>{" "} 248 реплики 249 </span> 250 ) 251 ) : ( 252 <span style={{ fontWeight: "normal" }}> 253 <span style={{ fontWeight: "bold" }}>{numReplies}</span>{" "} 254 реплика 255 </span> 256 )} 257 </EntityParam> 258 </EntityLi> 259 </EntityUl> 260 ); 261 })} 262 </div> 263 </> 264 ) : !fetchError ? ( 265 <div> 266 <p style={{ marginTop: "140px" }}>се вчитува...</p> 267 <Outlet /> 268 </div> 269 ) : ( 270 <div style={{ marginTop: "140px" }}> 271 <h1 style={{ textAlign: "center" }}>Страницата не е пронајдена.</h1> 272 </div> 273 ); 7 274 }; 8 275 -
reactapp/src/Pages/University.js
r8d83180 rc68150f 18 18 let params = useParams(); 19 19 const [loaded, setLoaded] = useState(false); 20 const [faculties, setFaculties] = useState( false);20 const [faculties, setFaculties] = useState(null); 21 21 const [fetchError, setFetchError] = useState(false); 22 22 … … 39 39 }, [params.universityId]); 40 40 41 return loaded ? (41 return loaded && !fetchError && faculties.length !== 0 ? ( 42 42 <> 43 43 <CurrentPageNav> … … 74 74 {faculty.facultyName} 75 75 </a> 76 <EntityParam >76 <EntityParam right="30px"> 77 77 {totalSections}{" "} 78 78 {totalSections !== 1 ? ( … … 103 103 </div> 104 104 </> 105 ) : !fetchError ? (105 ) : !fetchError && !loaded ? ( 106 106 <div> 107 107 <p style={{ marginTop: "140px" }}>се вчитува...</p> -
reactapp/src/Pages/UserDashboard.js
r8d83180 rc68150f 1 import React, { useEffect } from "react";1 import React, { useEffect, useState, useContext } from "react"; 2 2 import { 3 3 OpinionCard, 4 4 OpinionCardContent, 5 5 OpinionCardContentTime, 6 OpinionCardContentTitle,7 6 } from "../Components/Styled/OpinionCard.style"; 8 7 import { … … 11 10 } from "../Components/Styled/UserDetails.style"; 12 11 import { dateConverter } from "../Util/dateConverter"; 12 import axios from "../api/axios"; 13 import JSOG from "jsog"; 14 import AuthApi from "../api/AuthApi"; 13 15 14 function UserDashboard({ user, userLoaded }) { 16 function UserDashboard() { 17 const { auth, setAuth } = useContext(AuthApi); 18 19 const [user, setUser] = useState(null); 20 const [loadedUser, setLoadedUser] = useState(false); 21 const [fetchError, setFetchError] = useState(false); 22 15 23 useEffect(() => { 16 const timer = setTimeout(() => { 17 if (user === null) window.location.reload(false); 18 }, 3000); 19 return () => clearTimeout(timer); 24 const url = `http://192.168.0.17:8080/secure/currentUser`; 25 26 const fetchUser = async () => { 27 try { 28 const response = await axios.get(url, { withCredentials: true }); 29 var cyclicGraph = await response.data; 30 var jsogStructure = JSOG.encode(cyclicGraph); 31 cyclicGraph = JSOG.decode(jsogStructure); 32 setUser(cyclicGraph); 33 setLoadedUser(true); 34 } catch (error) { 35 setFetchError(true); 36 } 37 }; 38 39 if (auth) fetchUser(); 20 40 }, []); 21 41 22 return userLoaded ? ( 42 // useEffect(() => { 43 // const timer = setTimeout(() => { 44 // if (user === null) window.location.reload(false); <---- :-) 45 // }, 3000); 46 // return () => clearTimeout(timer); 47 // }, []); 48 49 function findParentThread(post) { 50 if (post.parent === null) return post; 51 return findParentThread(post.parent); 52 } 53 54 return loadedUser ? ( 23 55 <> 24 56 <h3>Кориснички податоци:</h3> … … 49 81 <OpinionCard> 50 82 <OpinionCardContent> 51 <p> 52 Во дискусија за{" "} 53 <a href={"/professor/" + post.targetProfessor.professorId}> 54 {post.targetProfessor.professorName} 55 </a> 83 <p style={{ fontStyle: "italic", marginBottom: "10px" }}> 84 во дискусија за{" "} 85 {post.targetProfessor !== undefined ? ( 86 <a href={"/professor/" + post.targetProfessor.professorId}> 87 {post.targetProfessor.professorName} 88 </a> 89 ) : ( 90 <a 91 href={ 92 post.parent === null 93 ? "/topic/" + post.postId 94 : "/topic/" + findParentThread(post).postId 95 } 96 > 97 {post.targetSubject.subjectName} 98 </a> 99 )} 56 100 </p> 57 <OpinionCardContentTitle>{post.title}</OpinionCardContentTitle> 58 <p>{post.content}</p> 101 <p style={{ marginBottom: "10px" }}>{post.content}</p> 59 102 <OpinionCardContentTime> 60 103 {dateConverter(
Note:
See TracChangeset
for help on using the changeset viewer.