Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated details dashboard logic to avoid merging 3 APIs and utilize f… #488

Merged
merged 5 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions __tests__/components/dashtable_v2.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@ import { render } from '@testing-library/react';
import React from 'react';
import GlobalDashboardTable from '../../components/dashtable_v2.js';

import {studentData, certifications, classroomId, timestamps, totalChallenges} from '../../testing_data/testing-data';
import {
studentData,
classroomId,
studentsAreEnrolledInSuperblocks,
totalChallenges
} from '../../testing_data/testing-data';

describe('GlobalDashboardTable', () => {
// Define a fixed time in milliseconds
const fixedTime = new Date('2016-03-09T12:00:00Z').getTime();

// Spy on Date.prototype.getTime and mock its implementation
const getTimeSpy = jest.spyOn(Date.prototype, 'getTime').mockImplementation(() => fixedTime);
const getTimeSpy = jest
.spyOn(Date.prototype, 'getTime')
.mockImplementation(() => fixedTime);

// Restore the original getTime method after the test
afterEach(() => {
Expand All @@ -20,13 +27,12 @@ describe('GlobalDashboardTable', () => {
const { container } = render(
<GlobalDashboardTable
studentData={studentData}
certifications={certifications}
classroomId={classroomId}
totalChallenges={totalChallenges}
timestamps={timestamps}
studentsAreEnrolledInSuperblocks={studentsAreEnrolledInSuperblocks}
/>
);
expect(getTimeSpy).toHaveBeenCalled();
expect(container).toMatchSnapshot();
});
});
});
62 changes: 62 additions & 0 deletions components/DetailsCSS.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.student_header {
display: flex;
font-size: 1.1rem;
margin: 10px;
border-bottom: 2px solid purple;
color: navy;
font-weight: 100;
background-color: hsl(194, 35%, 76%);
max-width: fit-content;
}

.board_container {
border: 4px solid black;
padding: 10px;
margin: 0px 5px 1px;
background-color: grey;
color: white;
}

.list_container {
display: flex;

flex-direction: row;
align-items: center;
gap: 10px;
}

.list_container h1 {
font-weight: bold;
font-size: 1.2rem;
}
.list_container button {
font-size: 0.7rem;
text-transform: uppercase;
border: 1px solid navy;

padding: 5px 10px;
background-color: orange;
}

.list_container button:hover {
background-color: rgb(89, 103, 174);
color: white;
}
.inner_comp {
background-color: grey;
color: white;
}

.details_progress_stats {
background-color: rgb(27, 15, 86);
color: white;
display: flex;
flex-direction: row;
justify-content: space-between;
border: 1px solid rgb(93, 0, 255);
padding: 10px;
}

.detailsBlockTitle {
font-size: 1;
}
46 changes: 46 additions & 0 deletions components/DetailsDashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import styles from './DetailsCSS.module.css';
import DetailsDashboardList from './DetailsDashboardList';
//getStudentProgressInSuperblock

import { getStudentProgressInSuperblock } from '../util/api_proccesor';

export default function DetailsDashboard(props) {
const printSuperblockTitle = individualSuperblockJSON => {
let indexOfTitleInSuperblockTitlesArray =
props.superblocksDetailsJSONArray.indexOf(individualSuperblockJSON);
let superblockTitle =
props.superblockTitles[indexOfTitleInSuperblockTitlesArray];
return superblockTitle;
};

const superblockProgress = superblockDashedName => {
let studentProgress = props.studentData;

return getStudentProgressInSuperblock(
studentProgress,
superblockDashedName
);
};

return (
<>
{props.superblocksDetailsJSONArray.map((arrayOfBlockObjs, idx) => {
let index = props.superblocksDetailsJSONArray.indexOf(arrayOfBlockObjs);
let superblockDashedName =
props.superblocksDetailsJSONArray[index][0].superblock;
let progressInBlocks = superblockProgress(superblockDashedName);
let superblockTitle = printSuperblockTitle(arrayOfBlockObjs);
return (
<div key={idx} className={styles.board_container}>
<DetailsDashboardList
superblockTitle={superblockTitle}
blockData={arrayOfBlockObjs}
studentProgressInBlocks={progressInBlocks}
></DetailsDashboardList>
</div>
);
})}
utsab marked this conversation as resolved.
Show resolved Hide resolved
</>
);
}
70 changes: 70 additions & 0 deletions components/DetailsDashboardList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react';
import { useState } from 'react';
import styles from './DetailsCSS.module.css';
import { getStudentTotalChallengesCompletedInBlock } from '../util/api_proccesor';

export default function DetailsDashboardList(props) {
const [hideDetails, setHideDetails] = useState(true);
const [buttonText, setButtonText] = useState('View details');

const handleShowDetails = () => {
if (hideDetails) {
setHideDetails(false);
} else {
setHideDetails(true);
}
utsab marked this conversation as resolved.
Show resolved Hide resolved

handleButtonText(hideDetails);
};

const handleButtonText = hideDetails => {
if (hideDetails) {
setButtonText('View less');
} else {
setButtonText('View details');
}
};

const getStudentsProgressInBlock = blockName => {
return getStudentTotalChallengesCompletedInBlock(
props.studentProgressInBlocks,
blockName
);
};

return (
<>
<div className={styles.list_container}>
<h1>{props.superblockTitle} </h1>

<button onClick={handleShowDetails}>{buttonText}</button>
</div>
<div className={styles.inner_comp}>
{hideDetails ? (
''
) : (
<>
<ul>
<li>
{props.blockData.map((blockDetails, idx) => {
return (
<div className={styles.details_progress_stats} key={idx}>
<h1 className={styles.detailsBlockTitle}>
{blockDetails.blockName}
</h1>
<h1 className={styles.focus}>
{getStudentsProgressInBlock(blockDetails.selector) +
'/' +
blockDetails.allChallenges.length}
</h1>
</div>
);
})}
</li>
</ul>
</>
)}
</div>
</>
);
}
11 changes: 5 additions & 6 deletions components/dashtable_v2.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
import { useTable } from 'react-table';
import React from 'react';
import getStudentActivity from './studentActivity';
import { extractStudentCompletionTimestamps } from '../util/api_proccesor';

export default function GlobalDashboardTable(props) {
let grandTotalChallenges = props.totalChallenges;

let rawStudentSummary = props.studentData.map(studentJSON => {
let email = studentJSON.email;
let completionTimestamps = [];

props.timestamps.forEach(timestampObj => {
if (timestampObj.name === email) {
completionTimestamps = timestampObj.completedTimestamps;
}
});
completionTimestamps = extractStudentCompletionTimestamps(
studentJSON.certifications
);

let rawStudentActivity = {
recentCompletions: completionTimestamps
};

let studentActivity = getStudentActivity(rawStudentActivity);

let numCompletions = completionTimestamps.length;

let percentageCompletion = (
Expand Down
51 changes: 34 additions & 17 deletions pages/dashboard/v2/[id].js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { getSession } from 'next-auth/react';
import GlobalDashboardTable from '../../../components/dashtable_v2';
import React from 'react';
import {
createDashboardObject,
getTotalChallenges,
createSuperblockDashboardObject,
getTotalChallengesForSuperblocks,
getDashedNamesURLs,
getSuperBlockJsons,
formattedStudentData,
getCompletionTimestamps
fetchStudentData,
checkIfStudentHasProgressDataForSuperblocksSelectedByTeacher
} from '../../../util/api_proccesor';

export async function getServerSideProps(context) {
Expand Down Expand Up @@ -58,35 +58,52 @@ export async function getServerSideProps(context) {
}
});

let formattedStudentDataResponse = await formattedStudentData();

let timestamps = getCompletionTimestamps(formattedStudentDataResponse);

let superblockURLS = await getDashedNamesURLs(
certificationNumbers.fccCertifications
);

let superBlockJsons = await getSuperBlockJsons(superblockURLS);
let dashboardObjs = createDashboardObject(superBlockJsons);
let totalChallenges = getTotalChallenges(dashboardObjs);
let superBlockJsons = await getSuperBlockJsons(superblockURLS); // this is an array of urls
utsab marked this conversation as resolved.
Show resolved Hide resolved
let dashboardObjs = await createSuperblockDashboardObject(superBlockJsons);

let totalChallenges = getTotalChallengesForSuperblocks(dashboardObjs);

let studentData = await fetchStudentData();

// Temporary check to map/accomodate hard-coded mock student data progress in unselected superblocks by teacher
let studentsAreEnrolledInSuperblocks =
checkIfStudentHasProgressDataForSuperblocksSelectedByTeacher(
studentData,
dashboardObjs
);
studentData.forEach(studentJSON => {
let indexToCheckProgress = studentData.indexOf(studentJSON);
let isStudentEnrolledInAtLeastOneSuperblock =
studentsAreEnrolledInSuperblocks[indexToCheckProgress].every(
val => val === true
);

if (!isStudentEnrolledInAtLeastOneSuperblock) {
studentData[indexToCheckProgress].certifications = [];
}
});

return {
props: {
userSession,
classroomId: context.params.id,
studentData: formattedStudentDataResponse,
studentData,
totalChallenges: totalChallenges,
timestamps: timestamps
studentsAreEnrolledInSuperblocks
}
};
}

export default function Home({
userSession,
studentData,
classroomId,
totalChallenges,
timestamps
studentData,
studentsAreEnrolledInSuperblocks
}) {
return (
<Layout>
Expand All @@ -106,10 +123,10 @@ export default function Home({
</div>
</Navbar>
<GlobalDashboardTable
studentData={studentData}
classroomId={classroomId}
timestamps={timestamps}
totalChallenges={totalChallenges}
studentData={studentData}
studentsAreEnrolledInSuperblocks={studentsAreEnrolledInSuperblocks}
></GlobalDashboardTable>
</>
)}
Expand Down
Loading