Skip to content

Commit

Permalink
Merge pull request #118 from Pearson-Advance/vue/PADV-1704
Browse files Browse the repository at this point in the history
PADV-1704 - Re-order options in dropdown menu (Classes table)
  • Loading branch information
sergivalero20 authored Oct 8, 2024
2 parents 3f57df1 + 4ccf0c7 commit c63c34a
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 40 deletions.
12 changes: 10 additions & 2 deletions src/features/Classes/Class/ClassPage/Actions.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { useParams, useHistory } from 'react-router-dom';
import { getConfig } from '@edx/frontend-platform';

Expand All @@ -15,12 +15,16 @@ import { useInstitutionIdQueryParam } from 'hooks';

import AddClass from 'features/Courses/AddClass';
import EnrollStudent from 'features/Classes/EnrollStudent';
import { fetchAllClassesData } from 'features/Classes/data/thunks';

const Actions = ({ previousPage }) => {
const dispatch = useDispatch();
const history = useHistory();
const { courseId, classId } = useParams();
const courseIdDecoded = decodeURIComponent(courseId);
const classIdDecoded = decodeURIComponent(classId);
const classes = useSelector((state) => state.classes.allClasses.data);
const selectedInstitution = useSelector((state) => state.main.selectedInstitution);

const classLink = `${getConfig().LEARNING_MICROFRONTEND_URL}/course/${classIdDecoded}/home`;

Expand All @@ -38,6 +42,10 @@ const Actions = ({ previousPage }) => {
history.push(addQueryParam(`/manage-instructors/${courseId}/${classId}?previous=${previousPage}`));
};

const finalCall = () => {
dispatch(fetchAllClassesData(selectedInstitution.id, courseIdDecoded));
};

return (
<>
<Button
Expand Down Expand Up @@ -89,7 +97,7 @@ const Actions = ({ previousPage }) => {
maxStudents: classInfo?.maxStudents,
}}
isEditing
isDetailClassPage
finalCall={finalCall}
/>
<EnrollStudent isOpen={isEnrollModalOpen} onClose={handleEnrollStudentModal} />
</>
Expand Down
10 changes: 6 additions & 4 deletions src/features/Classes/ClassesTable/_test_/columns.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ describe('columns', () => {
};

const {
getByText, getByTestId, getAllByRole, getAllByText,
getByText, getByTestId, getAllByRole,
} = renderWithProviders(
<MemoryRouter initialEntries={['/classes/']}>
<Route path="/classes/">
Expand All @@ -93,10 +93,12 @@ describe('columns', () => {

const button = getByTestId('droprown-action');
fireEvent.click(button);
const editButton = getAllByRole('button')[1];
const editButton = getAllByRole('button')[2];
expect(editButton).toBeInTheDocument();
fireEvent.click(editButton);
expect(getAllByText('Edit Class')).toHaveLength(2);
expect(getByText('course example')).toBeInTheDocument();
expect(getByText('View class content')).toBeInTheDocument();
expect(getByText('Manage Instructors')).toBeInTheDocument();
expect(getByText('Edit Class')).toBeInTheDocument();
expect(getByText('Delete Class')).toBeInTheDocument();
});
});
83 changes: 75 additions & 8 deletions src/features/Classes/ClassesTable/columns.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable react/prop-types */
import React from 'react';
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';

import {
Dropdown,
Expand All @@ -10,11 +11,19 @@ import {
import { Badge } from 'react-paragon-topaz';
import { MoreHoriz } from '@edx/paragon/icons';
import { getConfig } from '@edx/frontend-platform';
import { logError } from '@edx/frontend-platform/logging';

import AddClass from 'features/Courses/AddClass';
import DeleteModal from 'features/Common/DeleteModal';
import LinkWithQuery from 'features/Main/LinkWithQuery';

import { RequestStatus, initialPage } from 'features/constants';

import { deleteClass } from 'features/Courses/data/thunks';
import { fetchClassesData } from 'features/Classes/data/thunks';

import { formatUTCDate, setAssignStaffRole } from 'helpers';
import { resetClassState } from 'features/Courses/data/slice';

const columns = [
{
Expand Down Expand Up @@ -99,7 +108,51 @@ const columns = [
minStudentsAllowed,
maxStudents,
} = row.original;

const initialDeletionClassState = {
isModalOpen: false,
isRequestComplete: false,
};

const dispatch = useDispatch();
const institution = useSelector((state) => state.main.selectedInstitution);
const deletionState = useSelector((state) => state.courses.newClass.status);
const [isOpenModal, openModal, closeModal] = useToggle(false);
const [deletionClassState, setDeletionState] = useState(initialDeletionClassState);

const handleResetDeletion = () => {
setDeletionState(initialDeletionClassState);
dispatch(resetClassState());
};
const handleOpenDeleteModal = () => {
dispatch(resetClassState());
setDeletionState({ isModalOpen: true, isRequestComplete: false });
};

const handleDeleteClass = async (rowClassId) => {
try {
await dispatch(deleteClass(rowClassId));

setDeletionState({
isModalOpen: false,
isRequestComplete: true,
});

await dispatch(fetchClassesData(institution.id, initialPage));
} catch (error) {
logError(error);
} finally {
setDeletionState((prevState) => ({
...prevState,
isRequestComplete: true,
}));
}
};

const finalCall = () => {
dispatch(fetchClassesData(institution.id, initialPage));
};

return (
<Dropdown className="dropdowntpz">
<Dropdown.Toggle
Expand All @@ -112,26 +165,32 @@ const columns = [
alt="menu for actions"
/>
<Dropdown.Menu>
<Dropdown.Item onClick={openModal}>
<i className="fa-regular fa-pen-to-square mr-2 mb-1" />
Edit Class
</Dropdown.Item>
<Dropdown.Item
target="_blank"
rel="noreferrer"
onClick={() => setAssignStaffRole(`${getConfig().LEARNING_MICROFRONTEND_URL}/course/${classId}/home`, classId)}
className="text-truncate text-decoration-none custom-text-black"
>
<i className="fa-solid fa-arrow-up-right-from-square mr-2 mb-1" />
<i className="fa-regular fa-eye mr-2 mb-1" />
View class content
</Dropdown.Item>
<Dropdown.Item>
<LinkWithQuery
to={`/manage-instructors/${encodeURIComponent(masterCourseId)}/${encodeURIComponent(classId)}?previous=classes`}
to={`/manage-instructors/${encodeURIComponent(masterCourseId)}/${encodeURIComponent(classId)}`}
className="text-truncate text-decoration-none custom-text-black"
>
<i className="fa-regular fa-chalkboard-user mr-2 mb-1" />
Manage Instructors
</LinkWithQuery>
</Dropdown.Item>
<Dropdown.Item onClick={openModal}>
<i className="fa-solid fa-pencil mr-2 mb-1" />
Edit Class
</Dropdown.Item>
<Dropdown.Item onClick={handleOpenDeleteModal} className="text-danger">
<i className="fa-regular fa-trash mr-2 mb-1" />
Delete Class
</Dropdown.Item>
<AddClass
isOpen={isOpenModal}
onClose={closeModal}
Expand All @@ -145,8 +204,16 @@ const columns = [
minStudents: minStudentsAllowed,
maxStudents,
}}
isCoursePage
isEditing
finalCall={finalCall}
/>
<DeleteModal
isLoading={deletionState === RequestStatus.LOADING}
isOpen={deletionClassState.isModalOpen}
onClose={handleResetDeletion}
handleDelete={() => { handleDeleteClass(classId); }}
title="Delete this class"
textModal="This action will permanently delete this class and cannot be undone. Booked seat in this class will not be affected by this action."
/>
</Dropdown.Menu>
</Dropdown>
Expand Down
27 changes: 5 additions & 22 deletions src/features/Courses/AddClass/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,16 @@ import {
import { Button, Select } from 'react-paragon-topaz';
import { logError } from '@edx/frontend-platform/logging';

import { addClass, fetchCoursesData, editClass } from 'features/Courses/data';
import { addClass, editClass } from 'features/Courses/data';
import { fetchInstructorsOptionsData } from 'features/Instructors/data/thunks';
import { fetchClassesData, fetchAllClassesData } from 'features/Classes/data/thunks';
import { updateCurrentPage as updateCoursesCurrentPage } from 'features/Courses/data/slice';
import { updateCurrentPage as updateClassesCurrentPage } from 'features/Classes/data/slice';

import { initialPage } from 'features/constants';
import { formatUTCDate } from 'helpers';

import 'features/Courses/AddClass/index.scss';

const AddClass = ({
isOpen, onClose, courseInfo, isCoursePage, isEditing, isDetailClassPage,
isOpen, onClose, courseInfo, isEditing, finalCall,
}) => {
const dispatch = useDispatch();
const selectedInstitution = useSelector((state) => state.main.selectedInstitution);
Expand Down Expand Up @@ -56,12 +53,7 @@ const AddClass = ({
} catch (error) {
logError(error);
} finally {
if (isDetailClassPage) {
dispatch(fetchAllClassesData(selectedInstitution.id, courseInfo.masterCourseId));
} else {
dispatch(fetchClassesData(selectedInstitution.id, initialPage, courseInfo.masterCourseId));
dispatch(updateClassesCurrentPage(initialPage));
}
finalCall();
}
} else {
try {
Expand All @@ -79,13 +71,7 @@ const AddClass = ({
} catch (error) {
logError(error);
} finally {
if (isCoursePage) {
dispatch(fetchCoursesData(selectedInstitution.id, initialPage));
dispatch(updateCoursesCurrentPage(initialPage));
} else {
dispatch(fetchClassesData(selectedInstitution.id, initialPage, courseInfo.masterCourseId));
dispatch(updateClassesCurrentPage(initialPage));
}
finalCall();
}
}

Expand Down Expand Up @@ -269,15 +255,12 @@ AddClass.propTypes = {
minStudents: PropTypes.number,
maxStudents: PropTypes.number,
}).isRequired,
isCoursePage: PropTypes.bool,
isEditing: PropTypes.bool,
isDetailClassPage: PropTypes.bool,
finalCall: PropTypes.func.isRequired,
};

AddClass.defaultProps = {
isCoursePage: false,
isEditing: false,
isDetailClassPage: false,
};

export default AddClass;
8 changes: 7 additions & 1 deletion src/features/Courses/CourseDetailTable/columns.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { RequestStatus, initialPage } from 'features/constants';

import { deleteClass } from 'features/Courses/data/thunks';
import { fetchClassesData } from 'features/Classes/data/thunks';
import { updateCurrentPage as updateClassesCurrentPage } from 'features/Classes/data/slice';

import { resetClassState } from 'features/Courses/data/slice';

Expand Down Expand Up @@ -165,6 +166,11 @@ const columns = [
}
};

const finalCall = () => {
dispatch(fetchClassesData(institution.id, initialPage, masterCourseId));
dispatch(updateClassesCurrentPage(initialPage));
};

return (
<>
<Dropdown className="dropdowntpz">
Expand Down Expand Up @@ -217,8 +223,8 @@ const columns = [
minStudents: minStudentsAllowed,
maxStudents,
}}
isCoursePage
isEditing
finalCall={finalCall}
/>
<DeleteModal
isLoading={deletionState === RequestStatus.LOADING}
Expand Down
8 changes: 7 additions & 1 deletion src/features/Courses/CoursesDetailPage/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import CourseDetailTable from 'features/Courses/CourseDetailTable';

import { fetchClassesData } from 'features/Classes/data/thunks';
import { fetchCoursesData } from 'features/Courses/data/thunks';
import { fetchClassesDataSuccess } from 'features/Classes/data/slice';
import { fetchClassesDataSuccess, updateCurrentPage as updateClassesCurrentPage } from 'features/Classes/data/slice';
import { fetchCoursesDataSuccess, updateCurrentPage } from 'features/Courses/data/slice';

import { initialPage } from 'features/constants';
Expand Down Expand Up @@ -93,6 +93,11 @@ const CoursesDetailPage = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [institution, history]);

const finalCall = () => {
dispatch(fetchClassesData(institution.id, initialPage, courseIdDecoded));
dispatch(updateClassesCurrentPage(initialPage));
};

return (
<Container size="xl" className="px-4 mt-3">
<div className="d-flex justify-content-between mb-3 flex-column flex-sm-row">
Expand Down Expand Up @@ -137,6 +142,7 @@ const CoursesDetailPage = () => {
isOpen={isOpenModal}
onClose={closeModal}
courseInfo={nextCourseInfo}
finalCall={finalCall}
/>
</div>
<CourseDetailTable count={classes.count} data={classes.data} />
Expand Down
13 changes: 12 additions & 1 deletion src/features/Courses/CoursesTable/columns.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable react/prop-types, no-nested-ternary */
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useDispatch, useSelector } from 'react-redux';

import { Badge } from 'react-paragon-topaz';
import {
Expand All @@ -10,6 +11,9 @@ import { MoreHoriz } from '@edx/paragon/icons';

import AddClass from 'features/Courses/AddClass';
import LinkWithQuery from 'features/Main/LinkWithQuery';
import { updateCurrentPage as updateCoursesCurrentPage } from 'features/Courses/data/slice';
import { fetchCoursesData } from 'features/Courses/data/thunks';
import { initialPage } from 'features/constants';

const columns = [
{
Expand Down Expand Up @@ -44,8 +48,15 @@ const columns = [
cellClassName: 'dropdownColumn',
disableSortBy: true,
Cell: ({ row }) => {
const dispatch = useDispatch();
const selectedInstitution = useSelector((state) => state.main.selectedInstitution);
const [isOpenModal, openModal, closeModal] = useToggle(false);
const courseDetailsLink = `${getConfig().LEARNING_MICROFRONTEND_URL}/course/${row.original.masterCourseId}/home`;
const finalCall = () => {
dispatch(fetchCoursesData(selectedInstitution.id, initialPage));
dispatch(updateCoursesCurrentPage(initialPage));
};

return (
<Dropdown className="dropdowntpz">
<Dropdown.Toggle
Expand Down Expand Up @@ -73,7 +84,7 @@ const columns = [
masterCourseName: row.original.masterCourseName,
masterCourseId: row.original.masterCourseId,
}}
isCoursePage
finalCall={finalCall}
/>
</Dropdown.Menu>
</Dropdown>
Expand Down
2 changes: 1 addition & 1 deletion src/features/Courses/data/thunks.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function addClass(classData, instructorData) {
instructorData.append('class_id', response.data.class_id);
await dispatch(assignInstructors(instructorData));
}
dispatch(updateNotificationMsg(`${response.data.name} has been added successfullly!`));
dispatch(updateNotificationMsg(`${response.data.name} has been added successfully!`));
} catch (error) {
dispatch(newClassFailed());
logError(error);
Expand Down

0 comments on commit c63c34a

Please sign in to comment.