Skip to content

Commit 4e1bbd7

Browse files
daDevBoatkexanaDinoxhLSKprSailet03
authored
Prereq oaktree (#76)
* sidebar component add * tailwind workin, beggining page building * structure * fixed app * Main design layout * initial sidebar * courseView init * the course page initial tests * Make it run on my comuter * Tree without database integration * fixes * npm update * add to page * Biiiiig Refactoring * Broken version of prereq tree * Fixed not rendering anything. Still broken * Working v1 * handling #prereqs * Test * removed commented out code * More info expands now * More info expands now * More info expands now * Start coding on line 135 in PrereqTreePresenter Mr. PO * Prereqs colored and expands more info * added css styling * Fixed copy bug --------- Co-authored-by: kexana <deotsts@gmail.com> Co-authored-by: Sami Al Saati <sami.alsaati@hotmail.com> Co-authored-by: Kacper Lisik <lisik@kth.se> Co-authored-by: Elias Tosteberg <elias.tosteberg@gmail.com> Co-authored-by: Sailet03 <52610280+Sailet03@users.noreply.github.com>
1 parent 6461d03 commit 4e1bbd7

File tree

5 files changed

+128
-52
lines changed

5 files changed

+128
-52
lines changed

my-app/src/assets/example.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145248,4 +145248,4 @@
145248145248
"prerequisites_text": "null",
145249145249
"learning_outcomes": "null"
145250145250
}
145251-
}
145251+
}

my-app/src/model.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,17 @@ export const model = {
8484
entries.forEach(entry => {
8585
const course = {
8686
code: entry[1].code,
87-
name: entry[1]?.name ?? "",
88-
location: entry[1]?.location ?? "",
89-
department: entry[1]?.department ?? "",
90-
language: entry[1]?.language ?? "",
91-
description: entry[1]?.description ?? "",
92-
academicLevel: entry[1]?.academic_level ?? "",
93-
period: entry[1]?.period ?? "",
87+
name: entry[1]?.name ?? "null",
88+
location: entry[1]?.location ?? "null",
89+
department: entry[1]?.department ?? "null",
90+
language: entry[1]?.language ?? "null",
91+
description: entry[1]?.description ?? "null",
92+
academicLevel: entry[1]?.academic_level ?? "null",
93+
period: entry[1]?.period ?? "null",
9494
credits: entry[1]?.credits ?? 0,
95-
prerequisites: entry[1]?.prerequisites ?? "",
95+
prerequisites: entry[1]?.prerequisites ?? "null",
96+
prerequisites_text: entry[1]?.prerequisites_text ?? "null",
97+
learning_outcomes: entry[1]?.learning_outcomes ?? "null"
9698
};
9799
this.addCourse(course);
98100
});

my-app/src/presenters/ListViewPresenter.jsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const ListViewPresenter = observer(({ model }) => {
5959
const addFavourite = (course) => {
6060
model.addFavourite(course);
6161
}
62-
const removeFavourite = (course) => {
62+
const removeFavourite = (course) => {
6363
model.removeFavourite(course);
6464
}
6565
const handleFavouriteClick = (course) => {
@@ -72,8 +72,13 @@ const ListViewPresenter = observer(({ model }) => {
7272

7373
const [isPopupOpen, setIsPopupOpen] = useState(false);
7474
const [selectedCourse, setSelectedCourse] = useState(null);
75-
const preP = <PrerequisitePresenter model={model} selectedCourse={selectedCourse} />;
76-
const reviewPresenter = <ReviewPresenter model={model} course={selectedCourse}/>;
75+
const preP = <PrerequisitePresenter
76+
model={model}
77+
isPopupOpen={isPopupOpen}
78+
setIsPopupOpen={setIsPopupOpen}
79+
setSelectedCourse={setSelectedCourse}
80+
selectedCourse={selectedCourse} />;
81+
const reviewPresenter = <ReviewPresenter model={model} course={selectedCourse} />;
7782

7883
const popup = <CoursePagePopup
7984
favouriteCourses={model.favourites}
@@ -82,9 +87,9 @@ const ListViewPresenter = observer(({ model }) => {
8287
handleFavouriteClick={handleFavouriteClick}
8388
isOpen={isPopupOpen} onClose={() => setIsPopupOpen(false)}
8489
course={selectedCourse}
85-
prerequisiteTree={preP}
86-
reviewPresenter={reviewPresenter}/>
87-
90+
prerequisiteTree={preP}
91+
reviewPresenter={reviewPresenter} />
92+
8893

8994

9095
return <ListView

my-app/src/presenters/PrerequisitePresenter.jsx

Lines changed: 102 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ export const PrerequisitePresenter = observer((props) => {
2020
let uniqueCounter = 0;
2121
let textCounter = 0;
2222
let codeCounter = 0;
23-
//let toAdd = [];
23+
24+
let input_text_obj = {};
2425

2526
const position = { x: 0, y: 0 };
2627
const edgeType = 'smoothstep';
@@ -35,11 +36,8 @@ export const PrerequisitePresenter = observer((props) => {
3536
const nodeWidth = 172;
3637
const nodeHeight = 36;
3738

38-
//initialNodes.push(createNode("IK1203", "IK1203", "default"));
39-
//initialNodes.push(createNode("IK1204", "IK1204", "default"));
40-
//initialEdges.push(createEdge(props.selectedCourse.code, "IK1203"));
41-
//initialEdges.push(createEdge(props.selectedCourse.code, "IK1204"));
4239
loadTree(props.selectedCourse.code);
40+
console.log(initialNodes);
4341

4442
const getLayoutedElements = (nodes, edges, direction = 'LR') => {
4543
const isHorizontal = direction === 'LR';
@@ -79,9 +77,6 @@ export const PrerequisitePresenter = observer((props) => {
7977

8078

8179
const Flow = () => {
82-
//console.log("arived in Flow");
83-
84-
8580
const [nodes, setNodes, onNodesChange] = useNodesState(layoutedNodes);
8681
const [edges, setEdges, onEdgesChange] = useEdgesState(layoutedEdges);
8782

@@ -104,6 +99,7 @@ export const PrerequisitePresenter = observer((props) => {
10499
onNodesChange={onNodesChange}
105100
onEdgesChange={onEdgesChange}
106101
onConnect={onConnect}
102+
onNodeClick={clicked}
107103
connectionLineType={ConnectionLineType.SmoothStep}
108104
fitView
109105
style={{ backgroundColor: 'white', borderRadius: '10px'}}
@@ -119,8 +115,30 @@ export const PrerequisitePresenter = observer((props) => {
119115
</div>
120116

121117
);
122-
};
123118

119+
function setLabel(id, label) {
120+
setNodes((nodes) =>
121+
nodes.map((n) =>
122+
n.id === id ? { ...n, data: { ...n.data, label } } : n
123+
)
124+
);
125+
}
126+
127+
function clicked(event, node) {
128+
if (node["id"].split(" ")[0] === "text") {
129+
if (node["data"]["label"] === "More Info...") {
130+
node["style"]["zIndex"] = 1;
131+
setLabel(node["id"], <span>{input_text_obj[node["id"]]} <br/> <b style={{ color: 'blue' }}>CLOSE</b></span>);
132+
} else {
133+
node["style"]["zIndex"] = 0;
134+
setLabel(node["id"], "More Info...");
135+
}
136+
} else if (node["data"]["label"] !== "One of these" && node["data"]["label"] !== "No Prerequisites" && node["id"] !== props.selectedCourse.code) {
137+
// ADD FUNCTIONALITY FOR CLICKING COURSE CODE NODE (Tu eres muy retrasado y gordo)! :)
138+
// ONCLICK HERE
139+
}
140+
}
141+
};
124142

125143

126144

@@ -131,13 +149,15 @@ export const PrerequisitePresenter = observer((props) => {
131149
id: id,
132150
type: node_type,
133151
data: { label: name },
152+
style: { zIndex: 0 },
134153
position,
135154
};
136155
} else {
137156
return {
138157
id: id,
139158
type: node_type,
140159
data: { label: name },
160+
style: { zIndex: 0 },
141161
position,
142162
};
143163

@@ -148,18 +168,19 @@ export const PrerequisitePresenter = observer((props) => {
148168
}
149169

150170

151-
function prereq_convert(current_object, previous_key, previous_node_id) {
171+
function prereq_convert(courses_taken, current_object, previous_key, previous_node_id) {
172+
let current_node = null;
152173
if (current_object == undefined) {return}
153174

154175
if (!Array.isArray(current_object)) { // Is object
155176
let key = Object.keys(current_object)[0];
156-
//console.log("key: " + key);
157177
if (key == "or") {
158-
initialNodes.push(createNode(key + uniqueCounter, "One of these", "default"));
178+
current_node = createNode(key + uniqueCounter, "One of these", "default")
179+
initialNodes.push(current_node);
159180
initialEdges.push(createEdge(previous_node_id, key + uniqueCounter));
160-
prereq_convert(current_object[key], key, key + uniqueCounter++);
181+
prereq_convert(courses_taken, current_object[key], key, key + uniqueCounter++);
161182
} else if (key == "and") {
162-
prereq_convert(current_object[key], key, previous_node_id);
183+
prereq_convert(courses_taken, current_object[key], key, previous_node_id);
163184
}
164185

165186
} else { // Is an array
@@ -168,65 +189,109 @@ export const PrerequisitePresenter = observer((props) => {
168189
let input_id = "";
169190
let input_text = current_object[i];
170191
if (current_object[i].startsWith("#")) {
171-
input_text = "More Info..."; //input_text.slice(1, 115);
172-
input_id = "text" + ++textCounter;
192+
input_text = "More Info...";
193+
input_id = "text " + ++textCounter;
194+
input_text_obj[input_id] = current_object[i].slice(1);
173195
} else {
174196
input_id = current_object[i] + " " + ++codeCounter;
175197
}
176-
initialNodes.push(createNode(input_id, input_text, "output"));
198+
let new_node = createNode(input_id, input_text, "output");
199+
if (courses_taken.includes(current_object[i])) {
200+
new_node["style"]["backgroundColor"] = "lightgreen";
201+
current_object[i] = true;
202+
} else {
203+
current_object[i] = false;
204+
}
205+
current_node = new_node;
206+
initialNodes.push(new_node);
177207
initialEdges.push(createEdge(previous_node_id, input_id, "output"));
178208
} else {
179-
prereq_convert(current_object[i], previous_key, previous_node_id);
209+
prereq_convert(courses_taken, current_object[i], previous_key, previous_node_id);
180210
}
181211
}
182212
}
183-
184-
/*
213+
214+
/* STEP 2: Check if an object is true or false based on content of the inner object */
185215

186216
if (typeof current_object == "object" && !Array.isArray(current_object)) {
187217
let key = Object.keys(current_object)[0];
188218
let object_array = current_object[key];
189-
console.log(key);
190-
console.log(object_array);
191219
let num_of_matches = 0;
192220
for (let i = 0; i < object_array.length; i++) {
193221
if (Array.isArray(object_array[i])) {
194222
let num_of_inner_matches = 0;
195223
for (let j = 0; j < object_array[i].length; j++) {
196224
if (object_array[i][j]) {
197225
num_of_inner_matches ++;
226+
if (current_node != null) {
227+
current_node["style"]["backgroundColor"] = "lightgreen";
228+
}
229+
}
230+
}
231+
if (key == "or" && num_of_inner_matches > 0) {
232+
object_array[i] = true; num_of_matches++;
233+
if (current_node != null) {
234+
current_node["style"]["backgroundColor"] = "lightgreen";
235+
}
236+
continue;
237+
}
238+
if (key == "and" && num_of_inner_matches == object_array[i].length) {
239+
object_array[i] = true; num_of_matches++;
240+
if (current_node != null) {
241+
current_node["style"]["backgroundColor"] = "lightgreen";
198242
}
243+
continue;
199244
}
200-
if (key == "or" && num_of_inner_matches > 0) {object_array[i] = true; num_of_matches++; continue;}
201-
if (key == "and" && num_of_inner_matches == object_array[i].length) {object_array[i] = true; num_of_matches++; continue;}
202245
object_array[i] = false;
203246
} else if (typeof object_array[i] == "object") {
204247
let inner_key = Object.keys(object_array[i])[0];
205248
if (object_array[i][inner_key]) {num_of_matches++;}
206249
} else if(object_array[i]) {num_of_matches++}
207250
}
208-
if (key == "or" && num_of_matches > 0) {current_object[key] = true}
209-
else if (key == "and" && num_of_matches == object_array.length) {current_object[key] = true}
251+
if (key == "or" && num_of_matches > 0) {
252+
current_object[key] = true;
253+
if (current_node != null) {
254+
current_node["style"]["backgroundColor"] = "lightgreen";
255+
}
256+
}
257+
else if (key == "and" && num_of_matches == object_array.length) {
258+
current_object[key] = true;
259+
if (current_node != null) {
260+
current_node["style"]["backgroundColor"] = "lightgreen";
261+
}
262+
}
210263
else {current_object[key] = false}
211-
212264
}
213-
*/
265+
214266
}
215267

216-
function generateTree(prereqs) {
217-
console.log(JSON.stringify(prereqs, null, 4));
218-
prereq_convert(prereqs, null, props.selectedCourse.code);
268+
function generateTree(courses_taken, prereqs) {
269+
prereq_convert(courses_taken, prereqs, null, props.selectedCourse.code);
270+
let key = Object.keys(prereqs);
271+
return prereqs[key];
272+
219273
}
220274

221275

222-
function loadTree(course) {
223-
let root = createNode(props.selectedCourse.code, props.selectedCourse.code, "input")
224-
initialNodes.push(root);
276+
function loadTree(courses_taken) {
277+
278+
console.log(JSON.stringify(props.selectedCourse.prerequisites, null, 4));
279+
if (props.selectedCourse.prerequisites === "null" || props.selectedCourse.prerequisites.length == 0) {
280+
let display_node = createNode("No Prerequisites", "No Prerequisites", "default");
281+
display_node.style["pointerEvents"] = "none";
282+
display_node["className"] = 'no-handles';
283+
initialNodes.push(display_node);
284+
} else {
285+
let root = createNode(props.selectedCourse.code, props.selectedCourse.code, "input");
286+
let copy = JSON.parse(JSON.stringify(props.selectedCourse.prerequisites));
287+
let eligible = generateTree(JSON.parse(localStorage.getItem("completedCourses")), copy);
288+
if (eligible) {
289+
root["style"]["backgroundColor"] = "lightgreen";
290+
}
291+
initialNodes.push(root);
292+
}
225293

226-
generateTree(props.selectedCourse.prerequisites);
227294

228-
console.log(initialNodes);
229-
console.log(initialEdges);
230295
}
231296

232297
/* return <PrerequisiteTreeView initialNodes={initialNodes} initialEdges={initialEdges} /> */

my-app/src/styles.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@
1818
.font-kanit {
1919
font-family: var(--font-kanit);
2020
}
21+
22+
.react-flow__node.no-handles .react-flow__handle {
23+
display: none;
24+
}

0 commit comments

Comments
 (0)