Skip to content

Commit a11ae10

Browse files
authored
fix: CF-425: cleaning graph loading screen (#1039)
* feat: dark mode functionality added for editMarkModal's input and button elements * feat: dark mode improvement for editMarkModal's cancel button * feat: dark mode improvements for OptionHeader icons underneath the 'Term Planner' tab * feat: dark mode added for the select menu in the settingsMenu tooltip under the TermPlanner tab * feat: dark mode added to SettingMenu's DatePicker element * feat: dark mode for export button done + editModalMark bug fixed * fix: making sure the css for the select element in settingsMenu does not affect other select elements * feat: dark mode improvement for popconfirm for unplan wanring, import tooltip, also moved the button for import and export tooltip to common styles * feat: dark mode scrollbar added * feat: dark mode scrollbar on courseSelector menu had ugly white padding, fixed it to be #333 color instead * fix: href in courseSelector not very readable in dark mode, made the text a bit brighter and made a styled component for it * feat: dark mode added for search bar * feat: dark mode added for remove planner button * fix: forgot to add the new styles.ts file * feat: progressBar's text color and trailing color fixed * feat: dividing line in courseDescription changed from white to a dark grey * feat: bug icon turned into dark mode * feat: dark mode added for quick add and remove buttons in course menu * feat: courseProgression progress bar trailing color changed to dark grey * feat: progress on dark mode for graph, need to save this commit before I merge in the latest changes since the graph was changed * feat: dark mode for graph complete (nodes, arrows, hover states) + label now changes on hover (non-dark mode feature) * feat: buttons on graphical selector are dark mode * feat: saving progress on converting courseDescription panel to dark mode * feat: dark mode added to the sidebar * feat: sidebardrawer color changed, box shadow added to tabs so it looks more visible in dark mode * feat: new images added in help menu in course selector, dark mode versions added too * feat: TermPlanner's help menu tooltips now have dark mode pics and gifs * feat: highlight adjacent nodes and edges on hover * feat: highlight adjacent nodes opacity updated * refactor: graph.ts, changing function names and object names to be more readable: * feat: implemented a function that checks if a course is a prereq based on GraphData without calling the backend * fix: two graphs get rendered if you switch tabs fast enough * feat: created a function to store a hashmap of prereqs for later use for node styling * fix: updated the function that checks for coursePrerequisite Other options are: 1. Rely on GraphData, however it gets laggy when you hover over too many nodes 2. API call - would get slow with multiple requests 3. CourseEdge info gets stored into a hashmap at initialisation, so checking for prereqs is fast afterwards * refactor: graph.ts function and object names made more readable * refactor: rewriting the returns and using spread operator to reduce repetition in graph.ts * feat: highlight prerequisite nodes on hover * refactor: splitting functions up as they were getting too long * fix: if the dark mode button is toggled on and off, it repaints the canvas more than one time * feat: highlighted incoming edge if it's a prerequisite as well * feat: forgot to add pics into the HelpMenu for the new graphical selector hover node feature * feat: unlocked course nodes are now distinct from planned and locked courses feat: HelpMenu pictures were also updated * fix: adding and removing courses in graphical selector, updates the node in the graph without re-render refactor: graph.ts duplicate function removed * fix: endArrow opacity of graph was not changing on hover * fix: instead of using courseSlicer, used axios request to update unlocked nodes after adding to planner * fix: searchbar hidden while graph loads fix: random course node that pops up is hidden now feat: show all courses toggle has a loading screen now too * docs: forgot to update comment which I copy pasted in * fix: no-non-null-assertion warning fixed in graph.ts --------- Co-authored-by: Daysure <[email protected]>
1 parent df01a76 commit a11ae10

File tree

5 files changed

+59
-15
lines changed

5 files changed

+59
-15
lines changed

frontend/src/components/Spinner/Spinner.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ type Props = {
88
};
99

1010
const Spinner = ({ text }: Props) => (
11-
<S.Wrapper>
11+
<S.Wrapper className="loading-spinner">
1212
<Spin indicator={<LoadingOutlined style={{ fontSize: '2.5rem' }} spin />} />
13-
<div>{text}</div>
13+
<p>{text}</p>
1414
</S.Wrapper>
1515
);
1616

frontend/src/config/theme.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,20 @@ export const GlobalStyles = createGlobalStyle`
190190
box-shadow: ${({ theme }) => theme.graph?.tabBoxShadow} !important;
191191
}
192192
193+
// .spinner-wrapper .anticon anticon-loading anticon-spin ant-spin-dot {
194+
.spinner-wrapper .ant-spin-dot {
195+
color: ${({ theme }) => theme.graph.loadingIcon};
196+
}
197+
198+
.loading-spinner p {
199+
color: ${({ theme }) => theme.text};
200+
text-shadow:
201+
0.07em 0 ${({ theme }) => theme.graph.loadingText},
202+
0 0.07em ${({ theme }) => theme.graph.loadingText},
203+
-0.07em 0 ${({ theme }) => theme.graph.loadingText},
204+
0 -0.07em ${({ theme }) => theme.graph.loadingText};
205+
}
206+
193207
// Scrollbar settings
194208
/* width */
195209
::-webkit-scrollbar {
@@ -339,7 +353,8 @@ export const lightTheme: DefaultTheme = {
339353
borderColor: '#c2c2c2',
340354
tabColor: '#666',
341355
tabBottomBorderColor: '#f0f0f0',
342-
tabTextColor: '#000'
356+
tabTextColor: '#000',
357+
loadingText: '#fff'
343358
},
344359
sidebarDrawer: {
345360
backgroundColor: '#fff',
@@ -484,7 +499,9 @@ export const darkTheme: DefaultTheme = {
484499
tabColor: '#fff',
485500
tabBottomBorderColor: '#5d5d5d',
486501
tabTextColor: '#f1f1f1',
487-
tabBoxShadow: 'inset 16px 0 8px -8px rgba(255, 255, 255, 0.08)'
502+
tabBoxShadow: 'inset 16px 0 8px -8px rgba(255, 255, 255, 0.08)',
503+
loadingIcon: '#d7b7fd',
504+
loadingText: '#000'
488505
},
489506
sidebarDrawer: {
490507
backgroundColor: '#343239',

frontend/src/pages/GraphicalSelector/CourseGraph/CourseGraph.tsx

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ type Props = {
3939
fullscreen: boolean;
4040
focused?: string;
4141
hasPlannerUpdated: React.MutableRefObject<boolean>;
42+
loading: boolean;
43+
setLoading: React.Dispatch<React.SetStateAction<boolean>>;
4244
};
4345

4446
interface CoursePrerequisite {
@@ -50,7 +52,9 @@ const CourseGraph = ({
5052
handleToggleFullscreen,
5153
fullscreen,
5254
focused,
53-
hasPlannerUpdated
55+
hasPlannerUpdated,
56+
loading,
57+
setLoading
5458
}: Props) => {
5559
const { theme } = useSelector((state: RootState) => state.settings);
5660
const previousTheme = useRef<typeof theme>(theme);
@@ -61,8 +65,8 @@ const CourseGraph = ({
6165
const windowSize = useAppWindowSize();
6266

6367
const graphRef = useRef<Graph | null>(null);
64-
const initialising = useRef(false); // prevents multiple graphs being loaded
65-
const [loading, setLoading] = useState(true);
68+
const initialisingStart = useRef(false); // prevents multiple graphs being loaded
69+
const initialisingEnd = useRef(false); // unhide graph after loading complete
6670
const [unlockedCourses, setUnlockedCourses] = useState(false);
6771
const [prerequisites, setPrerequisites] = useState<CoursePrerequisite>({});
6872

@@ -185,6 +189,7 @@ const CourseGraph = ({
185189
nodeStrength: 2500,
186190
preventOverlap: true,
187191
onLayoutEnd: () => {
192+
initialisingEnd.current = true;
188193
setLoading(false);
189194
}
190195
},
@@ -205,8 +210,11 @@ const CourseGraph = ({
205210
edges: courseEdges
206211
};
207212

213+
// Hide graph until it's finished loaded, due to incomplete initial graph generation
208214
graphRef.current.data(data);
209215
graphRef.current.render();
216+
graphRef.current.getNodes().forEach((n) => n.hide());
217+
graphRef.current.getEdges().forEach((e) => e.hide());
210218

211219
graphRef.current.on('node:click', async (ev) => {
212220
// Clicking a node loads up course description for the course and set active
@@ -279,7 +287,7 @@ const CourseGraph = ({
279287

280288
const setupGraph = async () => {
281289
try {
282-
initialising.current = true;
290+
initialisingStart.current = true;
283291
const res = await Promise.allSettled([
284292
axios.get<GraphPayload>(`/programs/graph/${programCode}/${specs.join('+')}`),
285293
axios.post<CoursesAllUnlocked>(
@@ -300,7 +308,7 @@ const CourseGraph = ({
300308
}
301309
};
302310

303-
if (!initialising.current) setupGraph();
311+
if (!initialisingStart.current) setupGraph();
304312
if (hasPlannerUpdated.current) {
305313
hasPlannerUpdated.current = false;
306314
getUnlocked();
@@ -319,9 +327,19 @@ const CourseGraph = ({
319327
prerequisites,
320328
degree,
321329
planner,
322-
hasPlannerUpdated
330+
hasPlannerUpdated,
331+
setLoading
323332
]);
324333

334+
// Show all nodes and edges once graph is initially loaded
335+
useEffect(() => {
336+
if (initialisingEnd.current) {
337+
graphRef.current?.getNodes().forEach((n) => n.show());
338+
graphRef.current?.getEdges().forEach((e) => e.show());
339+
initialisingEnd.current = false;
340+
}
341+
}, [loading]);
342+
325343
const showAllCourses = () => {
326344
if (!graphRef.current) return;
327345
graphRef.current.getNodes().forEach((n) => n.show());
@@ -331,6 +349,7 @@ const CourseGraph = ({
331349
const showUnlockedCourses = useCallback(async () => {
332350
if (!graphRef.current) return;
333351
try {
352+
setLoading(true);
334353
const {
335354
data: { courses_state: coursesStates }
336355
} = await axios.post<CoursesAllUnlocked>(
@@ -349,11 +368,12 @@ const CourseGraph = ({
349368
n.getEdges().forEach((e) => e.hide());
350369
}
351370
});
371+
setLoading(false);
352372
} catch (e) {
353373
// eslint-disable-next-line no-console
354374
console.error('Error at showUnlockedCourses', e);
355375
}
356-
}, [degree, planner]);
376+
}, [degree, planner, setLoading]);
357377

358378
const handleZoomIn = () => {
359379
const viewportCenter = graphRef.current?.getViewPortCenterPoint();
@@ -406,7 +426,7 @@ const CourseGraph = ({
406426
return (
407427
<S.Wrapper ref={containerRef}>
408428
{loading ? (
409-
<S.SpinnerWrapper>
429+
<S.SpinnerWrapper className="spinner-wrapper">
410430
<Spinner text="Loading graph..." />
411431
</S.SpinnerWrapper>
412432
) : (

frontend/src/pages/GraphicalSelector/GraphicalSelector.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const GraphicalSelector = () => {
1414
const [fullscreen, setFullscreen] = useState(false);
1515
const [courseCode, setCourseCode] = useState<string | null>(null);
1616
const [activeTab, setActiveTab] = useState(HELP_TAB);
17+
const [loading, setLoading] = useState(true);
1718
const courseDescInfoCache = useRef({} as CourseDescInfoResCache);
1819
const hasPlannerUpdated = useRef<boolean>(false);
1920

@@ -54,10 +55,14 @@ const GraphicalSelector = () => {
5455
handleToggleFullscreen={() => setFullscreen((prevState) => !prevState)}
5556
focused={courseCode ?? undefined}
5657
hasPlannerUpdated={hasPlannerUpdated}
58+
loading={loading}
59+
setLoading={setLoading}
5760
/>
58-
<S.SearchBarWrapper>
59-
<CourseSearchBar onSelectCallback={setCourseCode} style={{ width: '25rem' }} />
60-
</S.SearchBarWrapper>
61+
{!loading && (
62+
<S.SearchBarWrapper>
63+
<CourseSearchBar onSelectCallback={setCourseCode} style={{ width: '25rem' }} />
64+
</S.SearchBarWrapper>
65+
)}
6166
{fullscreen && (
6267
<SidebarDrawer>
6368
<Tabs

frontend/src/styled.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ declare module 'styled-components' {
135135
tabBottomBorderColor: string;
136136
tabTextColor: string;
137137
tabBoxShadow?: string;
138+
loadingIcon?: string;
139+
loadingText: string;
138140
};
139141
sidebarDrawer: {
140142
backgroundColor: string;

0 commit comments

Comments
 (0)