|
1 | | -import Options from "../components/Options"; |
2 | | -import Display from "../components/Display"; |
3 | | -import Overlay from "../components/Overlay"; |
4 | | -import ReactDOM from 'react-dom/client'; |
5 | | -import React, {useState, useEffect, useRef} from "react"; |
6 | | -import {ThemeProvider,createTheme} from "@mui/material/styles"; |
7 | | -import TextField from '@mui/material/TextField'; |
8 | | -import Fab from "@mui/material/Fab"; |
9 | | -import Card from "@mui/material/Card"; |
10 | | -import Button from "@mui/material/Button"; |
11 | | -import {DarkModeSharp, LightModeRounded, HelpOutlineRounded, MailOutlineRounded} from "@mui/icons-material"; |
12 | | -// import {students as STUDENTS, rollToYear} from "../components/student_data_getter.tsx"; |
13 | | -import TreeCard from "../components/treeSCard"; |
14 | | -import SCard from "../components/SCard"; |
15 | | -import {Student as StudentType, Query as QueryType, Options as OptType} from "../components/commontypes"; |
16 | | -import GuestFooter from "../components/Treefooter"; |
17 | | - |
18 | | -//start shared search worker |
19 | | -if (!(typeof window === "undefined") && window.Worker) {//only on the client, TODO: find better method - do when dealing w/ SSG |
20 | | - var searcher = new Worker(new URL("../components/data_worker", import.meta.url)); |
21 | | -} |
22 | | - |
23 | | -const isIFrame = (typeof window !== "undefined") && (window.top === window.self); |
| 1 | +import { Card } from "@mui/material"; |
24 | 2 |
|
25 | 3 | export default function Home(props: Object) { |
26 | | - |
27 | | - const [students, setStudents]:[Array<StudentType>, Function] = useState([]); |
28 | | - const [darkMode, setDarkMode]=useState(true); |
29 | | - //initial render doesn't have access to localStorage so start off with true |
30 | | - const [currDisp, setCurr]:[any, Function] = useState(); |
31 | | - const [loading, setLoading] = useState(true); //loading at the start |
32 | | - const [listOpts, setOpts]:[OptType, Function] = useState({ |
33 | | - batch:["Loading..."], |
34 | | - hall:["Loading..."], |
35 | | - prog:["Loading..."], |
36 | | - dept:["Loading..."], |
37 | | - bloodgrp:["Loading..."] |
38 | | - }); |
39 | | - const [iFrame, setIFrame] = useState(false); |
40 | | - const searchBar = useRef<HTMLInputElement>(null); |
41 | | - |
42 | | - function queryHandler(event: any) { |
43 | | -// console.log("Query result received"); |
44 | | - if (event.data[0] == "query") { |
45 | | - setStudents(event.data[1].toSorted((a:StudentType, b:StudentType) => { |
46 | | - try { |
47 | | - return (Number(a.i) > Number(b.i)); |
48 | | - } catch (err) { |
49 | | - return (a.i > b.i); |
50 | | - } |
51 | | - })); |
52 | | -// setLoading(false); |
53 | | - } |
54 | | - } |
55 | | - |
56 | | - function treeHandler(event: any) { |
57 | | -// console.log("Tree result received"); |
58 | | - if (event.data[0] == "ft") { |
59 | | -// document.body.style.overflow = "hidden"; //hotfix |
60 | | - let [baapu, student, bacchas] = event.data[1]; |
61 | | - setCurr([ |
62 | | - <TreeCard |
63 | | - key="open" |
64 | | - data={student} |
65 | | - baapu={baapu /*TreeCard'll handle undefined*/} |
66 | | - bacchas={bacchas} |
67 | | - displayCard={displayCard} |
68 | | - clearOverlay={clearOverlay} |
69 | | - />, |
70 | | - <div className="footer-absolute" key="footer"> |
71 | | - <GuestFooter /> |
72 | | - </div> |
73 | | - ]); |
74 | | - } |
75 | | - |
76 | | - } |
77 | | - |
78 | | - function optsHandler(event: any) { |
79 | | - if (event.data[0] == "Options") { |
80 | | - setOpts(event.data[1]); |
81 | | - } |
82 | | - } |
83 | | - |
84 | | - function errorHandler(event: any) { |
85 | | - if (event.data === "Error") { |
86 | | - displayElement( |
87 | | - <Card><h1>Data could not be retrieved locally nor fetched.</h1> |
88 | | - <h2 >Please access the website from campus or via VPN once so that student data can be downloaded and stored.</h2> |
89 | | - <p>Check the console for more details.</p></Card> |
90 | | - ); |
91 | | - } |
92 | | - } |
93 | | - |
94 | | - useEffect(() => { |
95 | | - //on mount: set up worker handler, wait for it to initialise, and then: |
96 | | - //1. get list options from it |
97 | | - //2. set up the handlers for query and treecard |
98 | | -// console.log("waiting for worker"); |
99 | | - searcher.postMessage("ready?"); |
100 | | - searcher.onmessage = null; |
101 | | - searcher.onmessage = (event) => { |
102 | | - if (event.data !== "Worker ready") { |
103 | | - //error condition |
104 | | - errorHandler({data: "Error"}); |
105 | | - } else { |
106 | | - searcher.onmessage = (event) => { |
107 | | - if (event.data[0] != "Options") return; |
108 | | - setLoading(false); |
109 | | - setTimeout(() => { |
110 | | - if (searchBar.current) { |
111 | | - // console.log("focusing search bar"); |
112 | | - searchBar.current.focus(); |
113 | | - } |
114 | | - }, 0); //I don't know why but it just won't focus without a timeout |
115 | | - setOpts(event.data[1]); |
116 | | - searcher.onmessage = null; //remove this event handler |
117 | | - searcher.addEventListener("message", queryHandler); |
118 | | - searcher.addEventListener("message",treeHandler); |
119 | | - searcher.addEventListener("message", optsHandler); //when web worker updates, it will send out options again |
120 | | - searcher.addEventListener("message", errorHandler); |
121 | | - |
122 | | - }; |
123 | | - searcher.postMessage("Options"); |
124 | | - } |
125 | | - }; |
126 | | - return (() => {searcher.onmessage = null;}); //on unmount: remove all handlers |
127 | | - },[]) |
128 | | - |
129 | | - useEffect(() => { |
130 | | - setDarkMode(localStorage.getItem("darkmode") !== "false") |
131 | | - },[]); |
132 | | - //on mount: load darkmode setting |
133 | | - |
134 | | - useEffect(() => { |
135 | | - setIFrame(!isIFrame); |
136 | | - }, []); |
137 | | - //on mount: load the iframe stopper, need to do it this way so that static generation generates the page normally (isIFrame is false when building because typeof window is "undefined" then) but if the page is indeed an iframe, the app stops working |
138 | | - //can't stop iframes the normal way (setting HTTP header to disallow them) because github pages doesn't allow you to set HTTP headers :( |
139 | | - |
140 | | - const keydownfxn = (e: any) => { |
141 | | - if (e.key === "/" && searchBar.current && document.activeElement != searchBar.current) { |
142 | | - e.preventDefault(); |
143 | | - searchBar.current.focus(); |
144 | | - } else if (e.key === "Escape" && document.activeElement && document.activeElement instanceof HTMLElement) { |
145 | | - document.activeElement.blur(); |
146 | | - } |
147 | | - }; |
148 | | - |
149 | | - useEffect(() => { |
150 | | - document.addEventListener("keydown", keydownfxn); |
151 | | - return () => {document.removeEventListener("keydown", keydownfxn)} |
152 | | - }, []) |
153 | | - //on mount: add / button detection to move focus to search bar |
154 | | - |
155 | | - useEffect(() => { |
156 | | - if (darkMode) { |
157 | | - document.body.style.backgroundColor = "#000"; |
158 | | - } else { |
159 | | - document.body.style.backgroundColor = "#efefef"; |
160 | | - } |
161 | | - },[darkMode]); |
162 | | - |
163 | | - |
164 | | - const sendQuery = (query: QueryType)=> { |
165 | | - searcher.postMessage(query); |
166 | | -// console.log(query); |
167 | | -// setLoading(true); |
168 | | -// if (!workerReady) return []; |
169 | | - |
170 | | - } |
171 | | - |
172 | | - const clearOverlay = ()=> { |
173 | | - setCurr(undefined); |
174 | | -// document.body.style.overflow = "auto"; //hotfix |
175 | | - } |
176 | | - |
177 | | - const displayElement = (element: any) => { |
178 | | - clearOverlay(); |
179 | | - setCurr([element]); |
180 | | -// document.body.style.overflow = "hidden"; //hotfix |
181 | | - } |
182 | | - |
183 | | - const displayCard = (student: StudentType) =>{ |
184 | | - clearOverlay(); |
185 | | -// document.body.style.overflow = "hidden"; //hotfix |
186 | | - setCurr([<SCard |
187 | | - compact={false} |
188 | | - data={student} |
189 | | - key="closed" |
190 | | - > |
191 | | - <Button |
192 | | - onClick={() => {displayTree(student);}} |
193 | | - >Open Family Tree</Button> |
194 | | - </SCard>]); |
195 | | - } |
196 | | - |
197 | | - const displayTree = (student: StudentType) => { |
198 | | - clearOverlay(); |
199 | | - // if (!workerReady) return; |
200 | | - searcher.postMessage(["ft", student]); |
201 | | - } |
202 | | - |
203 | | - if (!iFrame) return ( |
204 | | - <div> |
205 | | - <ThemeProvider theme={darkMode |
206 | | - ? createTheme({ |
207 | | - palette:{ |
208 | | - mode: "dark", |
209 | | - } |
210 | | - }) |
211 | | - : createTheme({ |
212 | | - |
213 | | - }) |
214 | | - }> |
215 | | - <div |
216 | | - className="buttons" |
217 | | - style={{ |
218 | | - zIndex:"9999" |
219 | | - }} |
220 | | - > |
221 | | - <Fab |
222 | | - onClick={()=>{ |
223 | | - setDarkMode(!darkMode); |
224 | | - localStorage.setItem("darkmode", String(!darkMode));}} |
225 | | - > |
226 | | - {darkMode ? |
227 | | - <LightModeRounded /> |
228 | | - : <DarkModeSharp />} |
229 | | - </Fab> |
230 | | - <Fab |
231 | | - onClick={() => { |
232 | | - displayElement( |
233 | | - <Card |
234 | | - style={{ |
235 | | - padding:"10px" |
236 | | - }} |
237 | | - > |
238 | | - <h1>Setting a custom DP</h1> |
239 | | - <p>You can customise the image shown here by placing a custom image in your iitk webhome folder called dp.jpg/dp.png such that going to http://home.iitk.ac.in/~yourusername/dp opens up that particular picture.</p> |
240 | | - <h1>How do I update the data shown here?</h1> |
241 | | - <p>{`The data here is scraped from the Office Automation Portal. The data there can be updated via the Login Based Services > Student Profile > PI form . If you have had a branch change, please go to the ID Cell and update your ID Card to update your branch.`}</p> |
242 | | - <p>The changes if any will be reflected in about a week. </p> |
243 | | - <h1>{`I can't see students' pictures/I can't access student data.`}</h1> |
244 | | - <p>{`Access to student data is restricted to those currently on campus or connecting via VPN. Please visit the website once via either method so that the data can be stored locally. After this, you will be able to access student data from anywhere (as long as you don't wipe your cache or local files).`}</p> |
245 | | - <h1>Credits</h1> |
246 | | - <p>Student Search has gone through many iterations over the years. The current one was made by Deven Gangwani and Krishnansh Agrawal (both Y21).The one just before this was made by Yash Srivastav (Y15).</p> |
247 | | - <p>Credit for Student Guide data (bacche, ammas and baapus) goes to the Counselling Service, IITK.</p> |
248 | | - </Card> |
249 | | - ); |
250 | | - }} |
251 | | - > |
252 | | - <HelpOutlineRounded /> |
253 | | - </Fab> |
254 | | - <Fab |
255 | | - style={{ |
256 | | - display:(students.length < 3000 && students.length > 0 ? "" : "none") |
257 | | - }} |
258 | | - onClick={() => { |
259 | | - displayElement( |
260 | | - <Card |
261 | | - style={{ |
262 | | - padding:"10px", |
263 | | - width:"80vw", |
264 | | - maxWidth:"1200px", |
265 | | - maxHeight:"1000px" |
266 | | - }} |
267 | | - > |
268 | | - <p>{`Press the 'copy' button to copy all email addresses.`}</p> |
269 | | - <div |
270 | | - style={{ |
271 | | - height:"60vh", |
272 | | - overflow:"auto" |
273 | | - }} |
274 | | - > |
275 | | - {students.filter((el) => (el.u.length > 0)).map((el) => (el.u + "@iitk.ac.in")).join(", ")} |
276 | | - </div> |
277 | | - <Button |
278 | | - variant="contained" |
279 | | - onClick={() => { |
280 | | - navigator.clipboard.writeText(students.filter((el) => (el.u.length > 0)).map((el) => (el.u + "@iitk.ac.in")).join(", ")); |
281 | | - }} |
282 | | - >Copy</Button> |
283 | | - </Card> |
284 | | - ); |
285 | | - }} |
286 | | - > |
287 | | - <MailOutlineRounded /> |
288 | | - </Fab> |
289 | | - </div> |
290 | | - <Options |
291 | | - sendQuery={sendQuery} |
292 | | - listOpts={listOpts} |
293 | | - loading={loading} |
294 | | - ref={searchBar} |
295 | | - /> |
296 | | - <br/> |
297 | | - <Display |
298 | | - loading={loading} |
299 | | - toShow={students} |
300 | | - displayCard={displayCard} |
301 | | - /> |
302 | | - <Overlay |
303 | | - clearOverlay={clearOverlay} |
304 | | - > |
305 | | - {currDisp !== undefined |
306 | | - ? currDisp |
307 | | - : ""} |
308 | | - </Overlay> |
309 | | - </ThemeProvider> |
310 | | - </div> |
311 | | - ); |
312 | | - else return ( |
313 | | - <div style={{ |
314 | | - width: "60%", |
315 | | - margin:"auto", |
316 | | - color:"white" |
317 | | - }}><h1>Please view this page at <a href="https://search.pclub.in" target="_blank">search.pclub.in</a></h1> |
318 | | - <p>Credits:</p> |
319 | | - <p>Deven Gangwani</p> |
320 | | - <p>Krishnansh Agarwal</p> |
321 | | - <p>Programming Club, IITK</p> |
322 | | - </div> |
| 4 | + return ( |
| 5 | + <Card className="options bg-grey "> |
| 6 | + <div> |
| 7 | + <h2>Temporary Service Unavailable for Maintenance</h2> |
| 8 | + <p> |
| 9 | + As per the order of DDIA, Student Search portal will be unavailable |
| 10 | + until further notice. |
| 11 | + <br /> |
| 12 | + We are working with the administration to resolve the issue and will |
| 13 | + be back soon with the necessary updates. Thank you for your |
| 14 | + understanding. |
| 15 | + </p> |
| 16 | + </div> |
| 17 | + </Card> |
323 | 18 | ); |
324 | 19 | } |
325 | | - |
326 | | - |
0 commit comments