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

feat: add xpert summaries configuration by default for units #567

Merged
merged 2 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions src/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
@import "grading-settings/scss/GradingSettings";
@import "generic/styles";
@import "schedule-and-details/ScheduleAndDetails";
@import "pages-and-resources/PagesAndResources";
1 change: 1 addition & 0 deletions src/pages-and-resources/PagesAndResources.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import "./xpert-unit-summary/settings-modal/SettingsModal";
1 change: 1 addition & 0 deletions src/pages-and-resources/data/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export const getCourseAppsApiStatus = (state) => state.pagesAndResources.courseA
export const getCourseAppSettingValue = (setting) => (state) => (
state.pagesAndResources.courseAppSettings[setting]?.value
);
export const getResetStatus = (state) => state.pagesAndResources.resetStatus;
5 changes: 5 additions & 0 deletions src/pages-and-resources/data/slice.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const slice = createSlice({
courseAppIds: [],
loadingStatus: RequestStatus.IN_PROGRESS,
savingStatus: '',
resetStatus: '',
courseAppsApiStatus: {},
courseAppSettings: {},
},
Expand All @@ -22,6 +23,9 @@ const slice = createSlice({
updateSavingStatus: (state, { payload }) => {
state.savingStatus = payload.status;
},
updateResetStatus: (state, { payload }) => {
state.resetStatus = payload.status;
},
updateCourseAppsApiStatus: (state, { payload }) => {
state.courseAppsApiStatus = payload.status;
},
Expand All @@ -38,6 +42,7 @@ export const {
fetchCourseAppsSuccess,
updateLoadingStatus,
updateSavingStatus,
updateResetStatus,
updateCourseAppsApiStatus,
fetchCourseAppsSettingsSuccess,
updateCourseAppsSettingsSuccess,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ const XpertUnitSummarySettings = ({ intl }) => {
}
enableAppLabel={intl.formatMessage(messages.enableXpertUnitSummaryLabel)}
learnMoreText={intl.formatMessage(messages.enableXpertUnitSummaryLink)}
allUnitsEnabledText={intl.formatMessage(messages.allUnitsEnabledByDefault)}
noUnitsEnabledText={intl.formatMessage(messages.noUnitsEnabledByDefault)}
onClose={handleClose}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,12 @@ describe('XpertUnitSummarySettings', () => {
renderComponent();
});

test('Shows enabled if enabled from backend', async () => {
test('Shows switch on if enabled from backend', async () => {
expect(container.querySelector('#enable-xpert-unit-summary-toggle').checked).toBeTruthy();
expect(queryByTestId(container, 'enable-badge')).toBeTruthy();
});

test('Does not show enabled if disabled from backend', async () => {
test('Shows switch on if disabled from backend', async () => {
axiosMock.onGet(API.getXpertSettingsUrl(courseId))
.reply(200, generateCourseLevelAPIRepsonse({
success: true,
Expand All @@ -126,8 +126,25 @@ describe('XpertUnitSummarySettings', () => {

renderComponent();
await waitFor(() => expect(container.querySelector('#enable-xpert-unit-summary-toggle')).toBeTruthy());
expect(container.querySelector('#enable-xpert-unit-summary-toggle').checked).not.toBeTruthy();
expect(queryByTestId(container, 'enable-badge')).not.toBeTruthy();
expect(container.querySelector('#enable-xpert-unit-summary-toggle').checked).toBeTruthy();
expect(queryByTestId(container, 'enable-badge')).toBeTruthy();
});

test('Shows enable radio selected if enabled from backend', async () => {
await waitFor(() => expect(container.querySelector('#enable-xpert-unit-summary-toggle')).toBeTruthy());
expect(queryByTestId(container, 'enable-radio').checked).toBeTruthy();
});

test('Shows disable radio selected if enabled from backend', async () => {
axiosMock.onGet(API.getXpertSettingsUrl(courseId))
.reply(200, generateCourseLevelAPIRepsonse({
success: true,
enabled: false,
}));

renderComponent();
await waitFor(() => expect(container.querySelector('#enable-xpert-unit-summary-toggle')).toBeTruthy());
expect(queryByTestId(container, 'disable-radio').checked).toBeTruthy();
});
});

Expand All @@ -136,7 +153,7 @@ describe('XpertUnitSummarySettings', () => {
axiosMock.onGet(API.getXpertSettingsUrl(courseId))
.reply(400, generateCourseLevelAPIRepsonse({
success: false,
enabled: false,
enabled: undefined,
}));

renderComponent();
Expand All @@ -151,6 +168,12 @@ describe('XpertUnitSummarySettings', () => {

describe('saving configuration changes', () => {
beforeEach(() => {
axiosMock.onGet(API.getXpertSettingsUrl(courseId))
.reply(200, generateCourseLevelAPIRepsonse({
success: true,
enabled: false,
}));

axiosMock.onPost(API.getXpertSettingsUrl(courseId))
.reply(200, generateCourseLevelAPIRepsonse({
success: true,
Expand All @@ -164,8 +187,10 @@ describe('XpertUnitSummarySettings', () => {
jest.spyOn(API, 'postXpertSettings');

await waitFor(() => expect(container.querySelector('#enable-xpert-unit-summary-toggle')).toBeTruthy());
expect(queryByTestId(container, 'disable-radio').checked).toBeTruthy();
fireEvent.click(queryByTestId(container, 'enable-radio'));
fireEvent.click(getByText(container, 'Save'));
await waitFor(() => expect(container.querySelector('#enable-xpert-unit-summary-toggle')).not.toBeTruthy());
await waitFor(() => expect(container.querySelector('#enable-xpert-unit-summary-toggle')).toBeTruthy());
expect(API.postXpertSettings).toBeCalled();
});
});
Expand All @@ -186,4 +211,78 @@ describe('XpertUnitSummarySettings', () => {
expect(API.getXpertPluginConfigurable).toBeCalled();
});
});

describe('removing course configuration', () => {
beforeEach(() => {
axiosMock.onGet(API.getXpertSettingsUrl(courseId))
.reply(200, generateCourseLevelAPIRepsonse({
success: true,
enabled: true,
}));

axiosMock.onDelete(API.getXpertSettingsUrl(courseId))
.reply(200, generateCourseLevelAPIRepsonse({
success: true,
enabled: undefined,
}));

renderComponent();
});

test('Deleting course configuration', async () => {
jest.spyOn(API, 'deleteXpertSettings');

await waitFor(() => expect(container.querySelector('#enable-xpert-unit-summary-toggle')).toBeTruthy());
fireEvent.click(container.querySelector('#enable-xpert-unit-summary-toggle'));
fireEvent.click(getByText(container, 'Save'));
await waitFor(() => expect(container.querySelector('#enable-xpert-unit-summary-toggle')).toBeTruthy());
expect(API.deleteXpertSettings).toBeCalled();
});
});

describe('resetting course units', () => {
test('reset all units to be enabled', async () => {
axiosMock.onGet(API.getXpertSettingsUrl(courseId))
.reply(200, generateCourseLevelAPIRepsonse({
success: true,
enabled: true,
}));

axiosMock.onPost(API.getXpertSettingsUrl(courseId))
.reply(200, generateCourseLevelAPIRepsonse({
success: true,
enabled: true,
}));

renderComponent();

jest.spyOn(API, 'postXpertSettings');

await waitFor(() => expect(container.querySelector('#enable-xpert-unit-summary-toggle')).toBeTruthy());
fireEvent.click(queryByTestId(container, 'reset-units'));
expect(API.postXpertSettings).toBeCalledWith(courseId, { reset: true, enabled: true });
});

test('reset all units to be disabled', async () => {
axiosMock.onGet(API.getXpertSettingsUrl(courseId))
.reply(200, generateCourseLevelAPIRepsonse({
success: true,
enabled: false,
}));

axiosMock.onPost(API.getXpertSettingsUrl(courseId))
.reply(200, generateCourseLevelAPIRepsonse({
success: true,
enabled: false,
}));

renderComponent();

jest.spyOn(API, 'postXpertSettings');

await waitFor(() => expect(container.querySelector('#enable-xpert-unit-summary-toggle')).toBeTruthy());
fireEvent.click(queryByTestId(container, 'reset-units'));
expect(API.postXpertSettings).toBeCalledWith(courseId, { reset: true, enabled: false });
});
});
});
8 changes: 8 additions & 0 deletions src/pages-and-resources/xpert-unit-summary/data/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export async function postXpertSettings(courseId, state) {
const { data } = await getAuthenticatedHttpClient()
.post(getXpertSettingsUrl(courseId), {
enabled: state.enabled,
reset: state.reset,
});

return data;
Expand All @@ -31,3 +32,10 @@ export async function getXpertPluginConfigurable(courseId) {

return data;
}

export async function deleteXpertSettings(courseId) {
const { data } = await getAuthenticatedHttpClient()
.delete(getXpertSettingsUrl(courseId));

return data;
}
55 changes: 49 additions & 6 deletions src/pages-and-resources/xpert-unit-summary/data/thunks.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { getXpertSettings, postXpertSettings, getXpertPluginConfigurable } from './api';
import {
getXpertSettings, postXpertSettings, getXpertPluginConfigurable, deleteXpertSettings,
} from './api';

import { updateSavingStatus, updateLoadingStatus } from '../../data/slice';
import { updateSavingStatus, updateLoadingStatus, updateResetStatus } from '../../data/slice';
import { RequestStatus } from '../../../data/constants';

import { addModel, updateModel } from '../../../generic/model-store';
Expand All @@ -27,13 +29,13 @@ export function updateXpertSettings(courseId, state) {

export function fetchXpertPluginConfigurable(courseId) {
return async (dispatch) => {
let enabled = false;
let enabled;
dispatch(updateLoadingStatus({ status: RequestStatus.PENDING }));
try {
const { response } = await getXpertPluginConfigurable(courseId);
enabled = response?.enabled;
} catch (e) {
enabled = false;
enabled = undefined;
}

dispatch(addModel({
Expand All @@ -48,14 +50,14 @@ export function fetchXpertPluginConfigurable(courseId) {

export function fetchXpertSettings(courseId) {
return async (dispatch) => {
let enabled = false;
let enabled;
dispatch(updateLoadingStatus({ status: RequestStatus.PENDING }));

try {
const { response } = await getXpertSettings(courseId);
enabled = response?.enabled;
} catch (e) {
enabled = false;
enabled = undefined;
}

dispatch(addModel({
Expand All @@ -69,3 +71,44 @@ export function fetchXpertSettings(courseId) {
dispatch(updateLoadingStatus({ status: RequestStatus.SUCCESSFUL }));
};
}

export function removeXpertSettings(courseId) {
return async (dispatch) => {
dispatch(updateSavingStatus({ status: RequestStatus.PENDING }));

try {
const { response } = await deleteXpertSettings(courseId);
const { success } = response;
if (success) {
const model = { id: 'xpert-unit-summary', enabled: undefined };
dispatch(updateModel({ modelType: 'XpertSettings', model }));
dispatch(updateSavingStatus({ status: RequestStatus.SUCCESSFUL }));
return true;
}
dispatch(updateSavingStatus({ status: RequestStatus.FAILED }));
return false;
} catch (error) {
dispatch(updateSavingStatus({ status: RequestStatus.FAILED }));
return false;
}
};
}

export function resetXpertSettings(courseId, state) {
return async (dispatch) => {
dispatch(updateResetStatus({ status: RequestStatus.PENDING }));
try {
const { response } = await postXpertSettings(courseId, state);
const { success } = response;
if (success) {
dispatch(updateResetStatus({ status: RequestStatus.SUCCESSFUL }));
return true;
}
dispatch(updateResetStatus({ status: RequestStatus.FAILED }));
return false;
} catch (error) {
dispatch(updateResetStatus({ status: RequestStatus.FAILED }));
return false;
}
};
}
Loading