diff --git a/src/features/Common/data/_test_/api.test.js b/src/features/Common/data/_test_/api.test.js index b9849b49..72a19d46 100644 --- a/src/features/Common/data/_test_/api.test.js +++ b/src/features/Common/data/_test_/api.test.js @@ -56,7 +56,7 @@ describe('Common api services', () => { expect(httpClientMock.get).toHaveBeenCalledTimes(1); expect(httpClientMock.get).toHaveBeenCalledWith( - `${COURSE_OPERATIONS_API_V2}/license-pool/?limit=true&institution_id=1`, + `${COURSE_OPERATIONS_API_V2}/license-pool/?limit=true&institution_id=1&page=`, ); }); diff --git a/src/features/Common/data/api.js b/src/features/Common/data/api.js index c8f5e1b5..669dbfa3 100644 --- a/src/features/Common/data/api.js +++ b/src/features/Common/data/api.js @@ -12,9 +12,10 @@ function getCoursesByInstitution(institutionId, limit, page, filters) { ); } -function getLicensesByInstitution(institutionId, limit) { +function getLicensesByInstitution(institutionId, limit, page = '') { return getAuthenticatedHttpClient().get( - `${getConfig().COURSE_OPERATIONS_API_V2_BASE_URL}/license-pool/?limit=${limit}&institution_id=${institutionId}`, + `${getConfig().COURSE_OPERATIONS_API_V2_BASE_URL}/license-pool` + + `/?limit=${limit}&institution_id=${institutionId}&page=${page}`, ); } diff --git a/src/features/Courses/CoursesFilters/index.jsx b/src/features/Courses/CoursesFilters/index.jsx index 2d59c571..a04e019a 100644 --- a/src/features/Courses/CoursesFilters/index.jsx +++ b/src/features/Courses/CoursesFilters/index.jsx @@ -12,14 +12,10 @@ import { initialPage } from 'features/constants'; const CoursesFilters = ({ resetPagination }) => { const dispatch = useDispatch(); - const stateInstitution = useSelector((state) => state.main.institution.data); + const institutionSelected = useSelector((state) => state.main.institutionSelected); const stateCourses = useSelector((state) => state.courses.table.data); const [courseOptions, setCourseOptions] = useState([]); const [courseSelected, setCourseSelected] = useState(null); - let id = ''; - if (stateInstitution.length === 1) { - id = stateInstitution[0].id; - } const handleCoursesFilter = async (e) => { e.preventDefault(); @@ -29,14 +25,14 @@ const CoursesFilters = ({ resetPagination }) => { dispatch(updateFilters(formJson)); try { dispatch(updateCurrentPage(initialPage)); - dispatch(fetchCoursesData(id, initialPage, formJson)); + dispatch(fetchCoursesData(institutionSelected.id, initialPage, formJson)); } catch (error) { logError(error); } }; const handleCleanFilters = () => { - dispatch(fetchCoursesData(id)); + dispatch(fetchCoursesData(institutionSelected.id)); resetPagination(); setCourseSelected(null); dispatch(updateFilters({})); diff --git a/src/features/Courses/CoursesPage/_test_/index.test.jsx b/src/features/Courses/CoursesPage/_test_/index.test.jsx index f7b287ac..d1f48a60 100644 --- a/src/features/Courses/CoursesPage/_test_/index.test.jsx +++ b/src/features/Courses/CoursesPage/_test_/index.test.jsx @@ -1,58 +1,44 @@ import React from 'react'; -import axios from 'axios'; import CoursesPage from 'features/Courses/CoursesPage'; -import { - render, - waitFor, -} from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; import '@testing-library/jest-dom/extend-expect'; -import { Provider } from 'react-redux'; -import { initializeStore } from 'store'; - -let store; - -jest.mock('axios'); +import { renderWithProviders } from 'test-utils'; jest.mock('@edx/frontend-platform/logging', () => ({ logError: jest.fn(), })); -const mockResponse = { - data: { - results: [ - { - masterCourseName: 'Demo Course 1', - numberOfClasses: 1, - missingClassesForInstructor: null, - numberOfStudents: 1, - numberOfPendingStudents: 1, - }, - { - masterCourseName: 'Demo Course 2', - numberOfClasses: 1, - missingClassesForInstructor: 1, - numberOfStudents: 16, - numberOfPendingStudents: 0, - }, - ], - count: 2, - num_pages: 1, - current_page: 1, +const mockStore = { + courses: { + table: { + data: [ + { + masterCourseName: 'Demo Course 1', + numberOfClasses: 1, + missingClassesForInstructor: null, + numberOfStudents: 1, + numberOfPendingStudents: 1, + }, + { + masterCourseName: 'Demo Course 2', + numberOfClasses: 1, + missingClassesForInstructor: 1, + numberOfStudents: 16, + numberOfPendingStudents: 0, + }, + ], + count: 2, + num_pages: 1, + current_page: 1, + }, }, }; describe('CoursesPage', () => { - beforeEach(() => { - store = initializeStore(); - }); - it('renders courses data and pagination', async () => { - axios.get.mockResolvedValue(mockResponse); - - const component = render( - - - , + const component = renderWithProviders( + , + { preloadedState: mockStore }, ); waitFor(() => { diff --git a/src/features/Courses/CoursesPage/index.jsx b/src/features/Courses/CoursesPage/index.jsx index 2b935195..7b94c36f 100644 --- a/src/features/Courses/CoursesPage/index.jsx +++ b/src/features/Courses/CoursesPage/index.jsx @@ -11,19 +11,16 @@ import { fetchCoursesData } from 'features/Courses/data/thunks'; import { initialPage } from 'features/constants'; const CoursesPage = () => { - const stateInstitution = useSelector((state) => state.main.institution.data); + const institutionSelected = useSelector((state) => state.main.institutionSelected); const stateCourses = useSelector((state) => state.courses); const dispatch = useDispatch(); const [currentPage, setCurrentPage] = useState(initialPage); - // check this after implementation of selector institution - let id = ''; - if (stateInstitution.length === 1) { - id = stateInstitution[0].id; - } useEffect(() => { - dispatch(fetchCoursesData(id, currentPage, stateCourses.filters)); - }, [currentPage]); // eslint-disable-line react-hooks/exhaustive-deps + if (Object.keys(institutionSelected).length > 0) { + dispatch(fetchCoursesData(institutionSelected.id, currentPage, stateCourses.filters)); + } + }, [currentPage, institutionSelected, dispatch]); // eslint-disable-line react-hooks/exhaustive-deps const handlePagination = (targetPage) => { setCurrentPage(targetPage); diff --git a/src/features/Dashboard/DashboardPage/index.jsx b/src/features/Dashboard/DashboardPage/index.jsx index a7af99b4..d238b8df 100644 --- a/src/features/Dashboard/DashboardPage/index.jsx +++ b/src/features/Dashboard/DashboardPage/index.jsx @@ -17,13 +17,10 @@ const DashboardPage = () => { const history = useHistory(); const dispatch = useDispatch(); const stateInstitution = useSelector((state) => state.main.institution.data); + const institutionSelected = useSelector((state) => state.main.institutionSelected); const licenseData = useSelector((state) => state.dashboard.tableLicense.data); const [dataTableLicense, setDataTableLicense] = useState([]); - let idInstitution = ''; - // eslint-disable-next-line no-unused-expressions - stateInstitution.length > 0 ? idInstitution = stateInstitution[0].id : idInstitution = ''; - const handleViewAllLicenses = () => { history.push('/licenses'); dispatch(updateActiveTab('licenses')); @@ -42,13 +39,15 @@ const DashboardPage = () => { }, [licenseData]); useEffect(() => { - dispatch(fetchLicensesData(idInstitution)); - }, [idInstitution]); // eslint-disable-line react-hooks/exhaustive-deps + if (Object.keys(institutionSelected).length > 0) { + dispatch(fetchLicensesData(institutionSelected?.id)); + } + }, [institutionSelected, dispatch]); return (

- {stateInstitution.length === 1 ? `Welcome to ${stateInstitution[0].name}` : 'Select an institution'} + {Object.keys(institutionSelected).length > 0 ? `Welcome to ${institutionSelected?.name}` : `Welcome to ${stateInstitution[0]?.name}`}

diff --git a/src/features/Dashboard/InstructorAssignSection/ClassCard.jsx b/src/features/Dashboard/InstructorAssignSection/ClassCard.jsx index 6748da8b..2ca3b7ce 100644 --- a/src/features/Dashboard/InstructorAssignSection/ClassCard.jsx +++ b/src/features/Dashboard/InstructorAssignSection/ClassCard.jsx @@ -23,11 +23,15 @@ const ClassCard = ({ data }) => { }; ClassCard.propTypes = { - data: PropTypes.arrayOf(PropTypes.shape([])), + data: PropTypes.shape({ + className: PropTypes.string, + masterCourseName: PropTypes.string, + startDate: PropTypes.string, + }), }; ClassCard.defaultProps = { - data: [], + data: {}, }; export default ClassCard; diff --git a/src/features/Dashboard/InstructorAssignSection/index.jsx b/src/features/Dashboard/InstructorAssignSection/index.jsx index 338072ac..99b219d4 100644 --- a/src/features/Dashboard/InstructorAssignSection/index.jsx +++ b/src/features/Dashboard/InstructorAssignSection/index.jsx @@ -11,17 +11,16 @@ import 'features/Dashboard/InstructorAssignSection/index.scss'; const InstructorAssignSection = () => { const dispatch = useDispatch(); - const stateInstitution = useSelector((state) => state.main.institution.data); + const institutionSelected = useSelector((state) => state.main.institutionSelected); const classesData = useSelector((state) => state.dashboard.classes.data); const [classCards, setClassCards] = useState([]); - let idInstitution = ''; const numberOfClasses = 2; - // eslint-disable-next-line no-unused-expressions - stateInstitution.length > 0 ? idInstitution = stateInstitution[0].id : idInstitution = ''; useEffect(() => { - dispatch(fetchClassesData(idInstitution)); - }, [idInstitution]); // eslint-disable-line react-hooks/exhaustive-deps + if (Object.keys(institutionSelected).length > 0) { + dispatch(fetchClassesData(institutionSelected?.id)); + } + }, [institutionSelected, dispatch]); useEffect(() => { // Display only the first 'NumberOfClasses' on the homepage. @@ -36,7 +35,7 @@ const InstructorAssignSection = () => {

Instructor assignment

- {classCards.map(classInfo => )} + {classCards.map(classInfo => )} {classesData.length > numberOfClasses && (
diff --git a/src/features/Dashboard/data/_test_/redux.test.jsx b/src/features/Dashboard/data/_test_/redux.test.jsx index ef6cd563..ac4ce56f 100644 --- a/src/features/Dashboard/data/_test_/redux.test.jsx +++ b/src/features/Dashboard/data/_test_/redux.test.jsx @@ -28,8 +28,8 @@ describe('Dashboard redux tests', () => { }); test('successful fetch licenses data', async () => { - const licensesApiUrl = `${process.env.COURSE_OPERATIONS_API_V2_BASE_URL}/license-pool/` - + '?limit=false&institution_id=1'; + const licensesApiUrl = `${process.env.COURSE_OPERATIONS_API_V2_BASE_URL}/license-pool` + + '/?limit=false&institution_id=1&page='; const mockResponse = [ { licenseName: 'License Name 1', diff --git a/src/features/Instructors/InstructorsFilters/index.jsx b/src/features/Instructors/InstructorsFilters/index.jsx index 7dd05d13..d62c82d6 100644 --- a/src/features/Instructors/InstructorsFilters/index.jsx +++ b/src/features/Instructors/InstructorsFilters/index.jsx @@ -14,7 +14,7 @@ import PropTypes from 'prop-types'; import { initialPage } from 'features/constants'; const InstructorsFilters = ({ resetPagination }) => { - const stateInstitution = useSelector((state) => state.main.institution.data); + const institutionSelected = useSelector((state) => state.main.institutionSelected); const stateInstructors = useSelector((state) => state.instructors.courses); const currentPage = useSelector((state) => state.instructors.table.currentPage); const dispatch = useDispatch(); @@ -22,14 +22,9 @@ const InstructorsFilters = ({ resetPagination }) => { const [instructorName, setInstructorName] = useState(''); const [instructorEmail, setInstructorEmail] = useState(''); const [courseSelected, setCourseSelected] = useState(null); - // check this after implementation of selector institution - let id = ''; - if (stateInstitution.length === 1) { - id = stateInstitution[0].id; - } const handleCleanFilters = () => { - dispatch(fetchInstructorsData(currentPage)); + dispatch(fetchInstructorsData(institutionSelected?.id, currentPage)); resetPagination(); setInstructorName(''); setInstructorEmail(''); @@ -45,15 +40,17 @@ const InstructorsFilters = ({ resetPagination }) => { dispatch(updateFilters(formJson)); try { dispatch(updateCurrentPage(initialPage)); - dispatch(fetchInstructorsData(initialPage, formJson)); + dispatch(fetchInstructorsData(institutionSelected?.id, initialPage, formJson)); } catch (error) { logError(error); } }; useEffect(() => { - dispatch(fetchCoursesData(id)); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [id]); + if (Object.keys(institutionSelected).length > 0) { + dispatch(fetchCoursesData(institutionSelected.id)); + } + }, [institutionSelected, dispatch]); useEffect(() => { if (stateInstructors.data.length > 0) { diff --git a/src/features/Instructors/InstructorsPage/_test_/index.test.jsx b/src/features/Instructors/InstructorsPage/_test_/index.test.jsx index 8b8de30a..7f3b381b 100644 --- a/src/features/Instructors/InstructorsPage/_test_/index.test.jsx +++ b/src/features/Instructors/InstructorsPage/_test_/index.test.jsx @@ -1,58 +1,50 @@ import React from 'react'; -import axios from 'axios'; -import { - render, - waitFor, -} from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; import InstructorsPage from 'features/Instructors/InstructorsPage'; import '@testing-library/jest-dom/extend-expect'; -import { Provider } from 'react-redux'; -import { initializeStore } from 'store'; - -let store; - -jest.mock('axios'); +import { renderWithProviders } from 'test-utils'; jest.mock('@edx/frontend-platform/logging', () => ({ logError: jest.fn(), })); -const mockResponse = { - data: { - results: [ - { - instructorUsername: 'Instructor1', - instructorName: 'Instructor 1', - instructorEmail: 'instructor1@example.com', - ccxId: 'CCX1', - ccxName: 'CCX 1', - }, - { - instructorUsername: 'Instructor2', - instructorName: 'Instructor 2', - instructorEmail: 'instructor2@example.com', - ccxId: 'CCX2', - ccxName: 'CCX 2', - }, - ], - count: 2, - num_pages: 1, - current_page: 1, +const mockStore = { + instructors: { + table: { + data: [ + { + instructorUsername: 'Instructor1', + instructorName: 'Instructor 1', + instructorEmail: 'instructor1@example.com', + ccxId: 'CCX1', + ccxName: 'CCX 1', + }, + { + instructorUsername: 'Instructor2', + instructorName: 'Instructor 2', + instructorEmail: 'instructor2@example.com', + ccxId: 'CCX2', + ccxName: 'CCX 2', + }, + ], + count: 2, + num_pages: 1, + current_page: 1, + }, + classes: { + data: [], + }, + courses: { + data: [], + }, }, }; describe('InstructorPage', () => { - beforeEach(() => { - store = initializeStore(); - }); - test('render instructor page', () => { - axios.get.mockResolvedValue(mockResponse); - - const component = render( - - - , + const component = renderWithProviders( + , + { preloadedState: mockStore }, ); waitFor(() => { diff --git a/src/features/Instructors/InstructorsPage/index.jsx b/src/features/Instructors/InstructorsPage/index.jsx index a31ae6ca..ca1b8cce 100644 --- a/src/features/Instructors/InstructorsPage/index.jsx +++ b/src/features/Instructors/InstructorsPage/index.jsx @@ -13,12 +13,15 @@ import { initialPage } from 'features/constants'; const InstructorsPage = () => { const stateInstructors = useSelector((state) => state.instructors); + const institutionSelected = useSelector((state) => state.main.institutionSelected); const dispatch = useDispatch(); const [currentPage, setCurrentPage] = useState(initialPage); useEffect(() => { - dispatch(fetchInstructorsData(currentPage, stateInstructors.filters)); - }, [currentPage]); // eslint-disable-line react-hooks/exhaustive-deps + if (Object.keys(institutionSelected).length > 0) { + dispatch(fetchInstructorsData(institutionSelected.id, currentPage, stateInstructors.filters)); + } + }, [currentPage, institutionSelected, dispatch]); // eslint-disable-line react-hooks/exhaustive-deps const handlePagination = (targetPage) => { setCurrentPage(targetPage); diff --git a/src/features/Instructors/data/_test_/api.test.js b/src/features/Instructors/data/_test_/api.test.js index 70825fdf..1eb1c5e6 100644 --- a/src/features/Instructors/data/_test_/api.test.js +++ b/src/features/Instructors/data/_test_/api.test.js @@ -19,10 +19,11 @@ describe('getInstructorData', () => { }; const page = 1; + const institutionId = 1; getAuthenticatedHttpClient.mockReturnValue(httpClientMock); - getInstructorData(page); + getInstructorData(institutionId, page); expect(getAuthenticatedHttpClient).toHaveBeenCalledTimes(1); expect(getAuthenticatedHttpClient).toHaveBeenCalledWith(); @@ -30,7 +31,7 @@ describe('getInstructorData', () => { expect(httpClientMock.get).toHaveBeenCalledTimes(1); expect(httpClientMock.get).toHaveBeenCalledWith( 'http://localhost:18000/pearson_course_operation/api/v2/instructors/', - { params: { page } }, + { params: { page, institution_id: institutionId } }, ); }); }); diff --git a/src/features/Instructors/data/api.js b/src/features/Instructors/data/api.js index e90ae436..4b23009a 100644 --- a/src/features/Instructors/data/api.js +++ b/src/features/Instructors/data/api.js @@ -1,10 +1,11 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; import { getConfig } from '@edx/frontend-platform'; -function getInstructorData(page, filters) { +function getInstructorData(institutionId, page, filters) { const apiV2BaseUrl = getConfig().COURSE_OPERATIONS_API_V2_BASE_URL; const params = { page, + institution_id: institutionId, ...filters, }; diff --git a/src/features/Instructors/data/thunks.js b/src/features/Instructors/data/thunks.js index 09a6909d..c112c9ce 100644 --- a/src/features/Instructors/data/thunks.js +++ b/src/features/Instructors/data/thunks.js @@ -14,11 +14,11 @@ import { fetchClassesDataFailed, } from 'features/Instructors/data/slice'; -function fetchInstructorsData(currentPage, filtersData) { +function fetchInstructorsData(id, currentPage, filtersData) { return async (dispatch) => { dispatch(fetchInstructorsDataRequest()); try { - const response = camelCaseObject(await getInstructorData(currentPage, filtersData)); + const response = camelCaseObject(await getInstructorData(id, currentPage, filtersData)); dispatch(fetchInstructorsDataSuccess(response.data)); } catch (error) { dispatch(fetchInstructorsDataFailed()); diff --git a/src/features/Licenses/LicensesPage/_test_/index.test.jsx b/src/features/Licenses/LicensesPage/_test_/index.test.jsx index 765a42f9..09c30951 100644 --- a/src/features/Licenses/LicensesPage/_test_/index.test.jsx +++ b/src/features/Licenses/LicensesPage/_test_/index.test.jsx @@ -1,53 +1,42 @@ import React from 'react'; -import axios from 'axios'; -import { render, waitFor } from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; import LicensesPage from 'features/Licenses/LicensesPage'; import '@testing-library/jest-dom/extend-expect'; -import { Provider } from 'react-redux'; -import { initializeStore } from 'store'; - -let store; - -jest.mock('axios'); +import { renderWithProviders } from 'test-utils'; jest.mock('@edx/frontend-platform/logging', () => ({ logError: jest.fn(), })); -const mockResponse = { - data: { - results: [ - { - licenseName: 'License Name 1', - purchasedSeats: 20, - numberOfStudents: 6, - numberOfPendingStudents: 11, - }, - { - licenseName: 'License Name 2', - purchasedSeats: 10, - numberOfStudents: 1, - numberOfPendingStudents: 5, - }, - ], - count: 2, - num_pages: 1, - current_page: 1, +const mockStore = { + licenses: { + table: { + data: [ + { + licenseName: 'License Name 1', + purchasedSeats: 20, + numberOfStudents: 6, + numberOfPendingStudents: 11, + }, + { + licenseName: 'License Name 2', + purchasedSeats: 10, + numberOfStudents: 1, + numberOfPendingStudents: 5, + }, + ], + count: 2, + num_pages: 1, + current_page: 1, + }, }, }; describe('LicensesPage component', () => { - beforeEach(() => { - store = initializeStore(); - }); - test('renders licenses data components', () => { - axios.get.mockResolvedValue(mockResponse); - - const component = render( - - - , + const component = renderWithProviders( + , + { preloadedState: mockStore }, ); waitFor(() => { diff --git a/src/features/Licenses/LicensesPage/index.jsx b/src/features/Licenses/LicensesPage/index.jsx index 583a1ef0..a75a843d 100644 --- a/src/features/Licenses/LicensesPage/index.jsx +++ b/src/features/Licenses/LicensesPage/index.jsx @@ -11,22 +11,20 @@ import { initialPage } from 'features/constants'; const LicensesPage = () => { const dispatch = useDispatch(); - const stateInstitution = useSelector((state) => state.main.institution.data); + const institutionSelected = useSelector((state) => state.main.institutionSelected); const stateLicenses = useSelector((state) => state.licenses.table); const [currentPage, setCurrentPage] = useState(initialPage); - let idInstitution = ''; - // eslint-disable-next-line no-unused-expressions - stateInstitution.length > 0 ? idInstitution = stateInstitution[0].id : idInstitution = ''; - const handlePagination = (targetPage) => { setCurrentPage(targetPage); dispatch(updateCurrentPage(targetPage)); }; useEffect(() => { - dispatch(fetchLicensesData(idInstitution)); - }, [currentPage]); // eslint-disable-line react-hooks/exhaustive-deps + if (Object.keys(institutionSelected).length > 0) { + dispatch(fetchLicensesData(institutionSelected?.id, currentPage)); + } + }, [currentPage, institutionSelected, dispatch]); return ( diff --git a/src/features/Licenses/data/_test_/redux.test.jsx b/src/features/Licenses/data/_test_/redux.test.jsx index 3f46c00f..0a060ab5 100644 --- a/src/features/Licenses/data/_test_/redux.test.jsx +++ b/src/features/Licenses/data/_test_/redux.test.jsx @@ -29,7 +29,8 @@ describe('Licenses redux tests', () => { }); test('successful fetch licenses data', async () => { - const licensesApiUrl = `${process.env.COURSE_OPERATIONS_API_V2_BASE_URL}/license-pool/?limit=true&institution_id=1`; + const licensesApiUrl = `${process.env.COURSE_OPERATIONS_API_V2_BASE_URL}/license-pool` + + '/?limit=true&institution_id=1&page='; const mockResponse = { results: [ { @@ -65,7 +66,8 @@ describe('Licenses redux tests', () => { }); test('failed fetch licenses data', async () => { - const licensesApiUrl = `${process.env.COURSE_OPERATIONS_API_V2_BASE_URL}/license-pool/?limit=false&institution_id=1`; + const licensesApiUrl = `${process.env.COURSE_OPERATIONS_API_V2_BASE_URL}/license-pool` + + '/?limit=false&institution_id=1&page='; axiosMock.onGet(licensesApiUrl) .reply(500); diff --git a/src/features/Licenses/data/thunks.js b/src/features/Licenses/data/thunks.js index 70ac5558..3dbaf893 100644 --- a/src/features/Licenses/data/thunks.js +++ b/src/features/Licenses/data/thunks.js @@ -8,11 +8,11 @@ import { fetchLicensesDataFailed, } from 'features/Licenses/data/slice'; -function fetchLicensesData(id) { +function fetchLicensesData(id, currentPage) { return async (dispatch) => { dispatch(fetchLicensesDataRequest()); try { - const response = camelCaseObject(await getLicensesByInstitution(id, true)); + const response = camelCaseObject(await getLicensesByInstitution(id, true, currentPage)); dispatch(fetchLicensesDataSuccess(response.data)); } catch (error) { dispatch(fetchLicensesDataFailed()); diff --git a/src/features/Main/data/slice.js b/src/features/Main/data/slice.js index 254ba984..91abb12a 100644 --- a/src/features/Main/data/slice.js +++ b/src/features/Main/data/slice.js @@ -7,6 +7,7 @@ const initialState = { ...initialStateService, }, activeTab: 'dashboard', + institutionSelected: {}, }; export const mainSlice = createSlice({ @@ -26,6 +27,9 @@ export const mainSlice = createSlice({ updateActiveTab: (state, { payload }) => { state.activeTab = payload; }, + updateInstitutionSelected: (state, { payload }) => { + state.institutionSelected = payload; + }, }, }); @@ -34,6 +38,7 @@ export const { fetchInstitutionDataSuccess, fetchInstitutionDataFailed, updateActiveTab, + updateInstitutionSelected, } = mainSlice.actions; export const { reducer } = mainSlice; diff --git a/src/features/Main/index.jsx b/src/features/Main/index.jsx index f3422ff7..cabe21e7 100644 --- a/src/features/Main/index.jsx +++ b/src/features/Main/index.jsx @@ -1,27 +1,47 @@ -import React, { useEffect } from 'react'; -import { useDispatch } from 'react-redux'; +import React, { useEffect, useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; import { BrowserRouter, Switch, Route, Redirect, } from 'react-router-dom'; +import { getConfig } from '@edx/frontend-platform'; + import { Sidebar } from 'features/Main/Sidebar'; import { Header } from 'features/Main/Header'; import { Footer } from 'features/Main/Footer'; import StudentsPage from 'features/Students/StudentsPage'; -import Container from '@edx/paragon/dist/Container'; -import { getConfig } from '@edx/frontend-platform'; +import { Container, Row, Col } from '@edx/paragon'; import InstructorsPage from 'features/Instructors/InstructorsPage'; import CoursesPage from 'features/Courses/CoursesPage'; import DashboardPage from 'features/Dashboard/DashboardPage'; import LicensesPage from 'features/Licenses/LicensesPage'; +import { Select } from 'react-paragon-topaz'; + import { fetchInstitutionData } from 'features/Main/data/thunks'; +import { updateInstitutionSelected } from 'features/Main/data/slice'; + import './index.scss'; const Main = () => { const dispatch = useDispatch(); + const stateInstitutions = useSelector((state) => state.main.institution.data); + const institutionSelected = useSelector((state) => state.main.institutionSelected); + const [institutionOptions, setInstitutionOptions] = useState([]); useEffect(() => { dispatch(fetchInstitutionData()); - }, []); // eslint-disable-line react-hooks/exhaustive-deps + }, [dispatch]); + + useEffect(() => { + if (stateInstitutions.length > 0) { + const options = stateInstitutions.map(institution => ({ + ...institution, + label: institution.name, + value: institution.id, + })); + setInstitutionOptions(options); + dispatch(updateInstitutionSelected(options[0])); + } + }, [stateInstitutions, dispatch]); return ( @@ -30,6 +50,27 @@ const Main = () => {
+ {stateInstitutions.length > 1 && ( + + +

Select an institution

+