diff --git a/src/Components/DataPoints/DataPoints.css b/src/Components/DataPoints/DataPoints.css
index 996fb7f..05a5389 100644
--- a/src/Components/DataPoints/DataPoints.css
+++ b/src/Components/DataPoints/DataPoints.css
@@ -6,6 +6,7 @@
height: calc(100% - 2rem);
display: flex;
flex-direction: column;
+ position: relative;
}
.DataTableStyle {
@@ -37,7 +38,7 @@
.DataTableStyle .p-datatable-wrapper > .p-datatable-table > .p-datatable-thead,
.p-filter-column {
- height: 60px;
+ height: 50px;
}
.p-column-filter-row-items,
diff --git a/src/Components/DataPoints/DataPoints.jsx b/src/Components/DataPoints/DataPoints.jsx
index 9aa24e9..c5fe5aa 100644
--- a/src/Components/DataPoints/DataPoints.jsx
+++ b/src/Components/DataPoints/DataPoints.jsx
@@ -5,12 +5,11 @@ import {getPrograms} from "../../Data/ProgramData";
import {getRecordByRecordIDs} from "../../Data/RecordData";
import {Form, Outlet, redirect, useLoaderData, useNavigate, useParams} from "react-router-dom";
import './DataPoints.css';
-import React, {useEffect, useState} from "react";
+import React, {useEffect, useRef, useState} from "react";
import {
- Accordion, AccordionDetails, AccordionSummary,
- ButtonGroup,
+ Accordion, AccordionDetails, AccordionSummary, Box,
Chip, Dialog, DialogActions,
- DialogContent,
+ DialogContent, Fab,
IconButton, Paper, Tooltip, useTheme,
} from "@mui/material";
import {Check, Close, Explore, FilterAltOff, OpenInFull, Refresh} from "@mui/icons-material";
@@ -22,6 +21,7 @@ import {InlineTypography} from "../common";
import {ThemeSwitcherProvider} from 'react-css-theme-switcher';
import {TriStateCheckbox} from 'primereact/tristatecheckbox';
import {Dropdown} from "primereact/dropdown";
+import Draggable from "react-draggable";
export async function loader() {
// console.time("DataPointsLoader")
@@ -29,18 +29,9 @@ export async function loader() {
programs = Object.values(programs).flat().filter(program => program.Applicants.length > 0);
const recordIDs = programs.map(program => program.Applicants.map(applicant => applicant + "|" + program.ProgramID)).flat();
let records = Object.values(await getRecordByRecordIDs(recordIDs));
- records = records.map(record => {
- record['Season'] = record.ProgramYear + " " + record.Semester;
- return record;
- });
+ programs = programs.map(program => program.ProgramID);
records = records.sort((a, b) => {
- if (programs.indexOf(a.ProgramID) > programs.indexOf(b.ProgramID)) {
- return -1;
- } else if (programs.indexOf(a.ProgramID) < programs.indexOf(b.ProgramID)) {
- return 1;
- } else {
- return 0;
- }
+ return programs.indexOf(a.ProgramID) - programs.indexOf(b.ProgramID);
});
// console.timeEnd("DataPointsLoader")
@@ -100,9 +91,14 @@ export function ProgramContentInDataPoints() {
)
}
-export default function DataPoints() {
- const {records} = useLoaderData();
+export function DataGrid({records, insideProgramPage, style = {}}) {
const navigate = useNavigate();
+ const theme = useTheme();
+ const themeMap = {
+ light: "/TableLight.css",
+ dark: "/TableDark.css"
+ };
+
const [filters, setFilters] = useState(null);
useEffect(() => {
initFilters();
@@ -118,16 +114,6 @@ export default function DataPoints() {
Final: {value: null, matchMode: FilterMatchMode.EQUALS}
});
};
-
- const clearFilter = () => {
- initFilters();
- };
-
- const theme = useTheme();
- const themeMap = {
- light: "./TableLight.css",
- dark: "./TableDark.css"
- }
const getStatusColor = (status) => {
switch (status) {
case 'Reject':
@@ -216,7 +202,7 @@ export default function DataPoints() {
const programBodyTemplate = (rowData) => {
return
-
+
navigate(`/datapoints/program/${rowData.ProgramID}`)}>
@@ -240,130 +226,105 @@ export default function DataPoints() {
return value.includes(filters);
})
- const renderHeader = () => {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- );
- };
-
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ {insideProgramPage ? null : }
+
+
+
+
+
+
+
+
)
}
@@ -382,7 +343,8 @@ function UsageGuidance() {
-
- 对于申请人和申请项目这两列,可点击单元格右侧按钮查看申请人或项目的详细信息。
+ 对于申请人和申请项目这两列,可点击单元格右侧按钮查看申请人或项目的详细信息。
- 本页面为只读模式,想要编辑自己的申请人信息或添加/删除/修改所申请的项目,请点击右上角头像下拉菜单中Profile页面编辑相应信息。
@@ -400,4 +362,50 @@ function UsageGuidance() {
);
-}
\ No newline at end of file
+}
+
+export default function DataPoints() {
+ const loaderRecords = useLoaderData();
+ const records = loaderRecords.records.map(record => {
+ record['Season'] = record.ProgramYear + " " + record.Semester;
+ return record;
+ });
+
+ const nodeRef = useRef(null);
+
+ const dragStartPositionXYRef = useRef({x: 0, y: 0});
+
+ return (
+ <>
+
+
+
+
+
+
+ {
+ dragStartPositionXYRef.current = {x: data.x, y: data.y};
+ }}
+ onStop={(event, data) => {
+ const THRESHOLD = 2;
+ const {x, y} = dragStartPositionXYRef.current ?? {x: 0, y: 0};
+ const wasDragged = Math.abs(data.x - x) > THRESHOLD || Math.abs(data.y - y) > THRESHOLD;
+ if (!wasDragged) {
+ event.preventDefault();
+ document.querySelector(".HiddenRefreshButton").click()
+ }
+ }}
+ >
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/src/Components/HowToUse/HowToUse.jsx b/src/Components/HowToUse/HowToUse.jsx
index 5b31c6d..7d90984 100644
--- a/src/Components/HowToUse/HowToUse.jsx
+++ b/src/Components/HowToUse/HowToUse.jsx
@@ -37,17 +37,17 @@ function Graduated({loaderData}) {
}
>
- 毕业生或毕业年级请阅读:
+ 毕业生或大四研三请阅读:
- 我来这个网站应该干啥?
- 为了给SIST学弟学妹们提供更多海外申请的信息,我们希望你能做三件事情:
+ 我来这个网站应该干什么?
+ 为了给SIST学弟学妹们提供更多海外申请的信息,我们希望你能抽出宝贵的15分钟,做三件事情:
-
贡献自己申请时的背景(可选匿名)。考虑到有的人也许会有多于一年的申请经历,因此每个用户可添加多个申请人,以申请年份作区分。
-
- 贡献自己的申请记录,也就是你申请的各个项目的admit/reject的结果,最终呈现出来的就像在一亩三分地或opencs上浏览申请结果一样。
+ 尽可能多地贡献自己的申请记录,也就是你申请的各个项目的admit/reject的结果,最终呈现出来的就像在一亩三分地或opencs上浏览申请结果一样。
-
贡献海外高校graduate program信息,如果你对某些项目有着很深入的了解,我们希望你把你了解到的给写上,这样能为学弟学妹们提供更多insight。
@@ -67,7 +67,7 @@ function Graduated({loaderData}) {
)
diff --git a/src/Components/Profile/UserInfo/ProfileHeader.jsx b/src/Components/Profile/UserInfo/ProfileHeader.jsx
index 225cd13..55bd847 100644
--- a/src/Components/Profile/UserInfo/ProfileHeader.jsx
+++ b/src/Components/Profile/UserInfo/ProfileHeader.jsx
@@ -23,7 +23,7 @@ import "./ProfileHeader.css";
import {Form, Link} from "react-router-dom";
import PersonOutlineIcon from '@mui/icons-material/PersonOutline';
import PersonAddAltIcon from '@mui/icons-material/PersonAddAlt';
-import {ConnectWithoutContact, Edit, Refresh, HomeRounded, LinkedIn, Link as LinkIcon} from "@mui/icons-material";
+import {ConnectWithoutContact, Edit, Refresh, HomeRounded, LinkedIn, Link as LinkIcon, Mail} from "@mui/icons-material";
import {blue, grey} from "@mui/material/colors";
import {CollapseSideBar} from "../../common";
import React, {useState} from "react";
@@ -182,6 +182,8 @@ export function ProfileHeader({loaderData}) {
} contact={contact}
setContact={setContact}/>
+ } contact={contact}
+ setContact={setContact}/>
} contact={contact}
setContact={setContact}/>
} contact={contact}
diff --git a/src/Components/ProgramPage/ProgramContent/ProgramContent.jsx b/src/Components/ProgramPage/ProgramContent/ProgramContent.jsx
index 7a360c2..c1423b3 100644
--- a/src/Components/ProgramPage/ProgramContent/ProgramContent.jsx
+++ b/src/Components/ProgramPage/ProgramContent/ProgramContent.jsx
@@ -1,19 +1,24 @@
import React from 'react';
import ReactMarkdown from 'react-markdown';
import './ProgramContent.css'
-import {Form, Link, useLoaderData} from "react-router-dom";
+import {Form, Link, redirect, useLoaderData} from "react-router-dom";
import {getProgramContent, getProgramDesc} from "../../../Data/ProgramData";
-import {IconButton, Typography} from "@mui/material";
+import {IconButton, Paper, Typography} from "@mui/material";
import {Edit, Refresh} from "@mui/icons-material";
import remarkGfm from 'remark-gfm'
+import {getRecordByProgram} from "../../../Data/RecordData";
+import {DataGrid} from "../../DataPoints/DataPoints";
+import {useSmallPage} from "../../common";
export async function loader({params}) {
// console.time("ProgramContentLoader")
const programId = params.programId;
+ let records = await getRecordByProgram(programId);
+ records = Object.values(records);
try {
const programContent = await getProgramContent(programId);
// console.timeEnd("ProgramContentLoader")
- return {programContent};
+ return {programContent, records};
} catch (e) {
throw e;
}
@@ -21,15 +26,17 @@ export async function loader({params}) {
export async function action({params}) {
const programId = params.programId;
- return await getProgramDesc(programId, true);
+ await getProgramDesc(programId, true);
+ return await getRecordByProgram(programId, true);
}
function ProgramContent({editable = true}) {
- const {programContent} = useLoaderData();
+ const {programContent, records} = useLoaderData();
+ const smallPage = useSmallPage();
return (
<>
-
+
{programContent.ProgramID}
{editable ?
@@ -43,12 +50,15 @@ function ProgramContent({editable = true}) {
: null}
-
- {programContent.description}
-
+
+
+ {programContent.description}
+
+
+
>
);
}
diff --git a/src/Components/TopBar/StatusBlock/StatusBlock.jsx b/src/Components/TopBar/StatusBlock/StatusBlock.jsx
index 0f49acd..905e3d5 100644
--- a/src/Components/TopBar/StatusBlock/StatusBlock.jsx
+++ b/src/Components/TopBar/StatusBlock/StatusBlock.jsx
@@ -11,11 +11,9 @@ import Brightness4Icon from '@mui/icons-material/Brightness4';
import Brightness7Icon from '@mui/icons-material/Brightness7';
export async function loader() {
- // console.time("HomeLoader")
const displayName = await getDisplayName();
- const metaData = await getMetaData();
- const avatarUrl = await getAvatar(metaData?.Avatar);
- // console.timeEnd("HomeLoader")
+ const metaData = await getMetaData(displayName);
+ const avatarUrl = await getAvatar(metaData?.Avatar, displayName);
return {displayName, avatarUrl};
}
diff --git a/src/Data/UserData.js b/src/Data/UserData.js
index 90bb052..df3c5f2 100644
--- a/src/Data/UserData.js
+++ b/src/Data/UserData.js
@@ -38,7 +38,6 @@ export async function login(email, password) {
expireAt: data.expireAt,
}
await setUserInfo(user_info);
- await getDisplayName();
return redirect("/");
}
}
diff --git a/src/index.css b/src/index.css
index 508db03..5613be8 100644
--- a/src/index.css
+++ b/src/index.css
@@ -12,7 +12,7 @@ body,html {
/* Works on Chrome/Edge/Safari */
*::-webkit-scrollbar {
- width: 12px;
+ width: 5px;
}
*::-webkit-scrollbar-track {
background: transparent;