-
+
{urlLms && (
diff --git a/src/courseware/course/masquerade-widget/MasqueradeWidget.jsx b/src/courseware/course/masquerade-widget/MasqueradeWidget.jsx
new file mode 100644
index 00000000..864a571e
--- /dev/null
+++ b/src/courseware/course/masquerade-widget/MasqueradeWidget.jsx
@@ -0,0 +1,73 @@
+import React, {
+ Component,
+} from 'react';
+import PropTypes from 'prop-types';
+
+import { Dropdown } from '@edx/paragon';
+
+import { getMasqueradeOptions } from '../../../data/api';
+import MasqueradeWidgetOption from './MasqueradeWidgetOption';
+
+class MasqueradeWidget extends Component {
+ constructor(props) {
+ super(props);
+ this.courseId = props.courseId;
+ this.state = {
+ options: [],
+ };
+ }
+
+ componentDidMount() {
+ getMasqueradeOptions(this.courseId).then((data) => {
+ if (data.success) {
+ const options = this.parseAvailableOptions(data);
+ this.setState({
+ options,
+ });
+ } else {
+ console.warn('Unable to get masquerade options', data);
+ }
+ }).catch((response) => {
+ console.error('Unable to get masquerade options', response);
+ });
+ }
+
+ parseAvailableOptions(payload) {
+ const data = payload || {};
+ const active = data.active || {};
+ const available = data.available || [];
+ const options = available.map((group) => (
+
+ ));
+ return options;
+ }
+
+ render() {
+ const {
+ options,
+ } = this.state;
+ return (
+
+
+ View this course as
+
+
+ {options}
+
+
+ );
+ }
+}
+MasqueradeWidget.propTypes = {
+ courseId: PropTypes.string.isRequired,
+};
+export default MasqueradeWidget;
diff --git a/src/courseware/course/masquerade-widget/MasqueradeWidgetOption.jsx b/src/courseware/course/masquerade-widget/MasqueradeWidgetOption.jsx
new file mode 100644
index 00000000..b7a2d1a4
--- /dev/null
+++ b/src/courseware/course/masquerade-widget/MasqueradeWidgetOption.jsx
@@ -0,0 +1,90 @@
+import React, {
+ Component,
+} from 'react';
+import PropTypes from 'prop-types';
+import { Dropdown } from '@edx/paragon';
+
+import { postMasqueradeOptions } from '../../../data/api';
+
+class MasqueradeWidgetOption extends Component {
+ handleClick() {
+ const {
+ courseId,
+ groupId,
+ role,
+ userName,
+ userPartitionId,
+ } = this.props;
+ const payload = {};
+ if (role) {
+ payload.role = role;
+ }
+ if (groupId) {
+ payload.group_id = parseInt(groupId, 10);
+ payload.user_partition_id = parseInt(userPartitionId, 10);
+ }
+ if (userName) {
+ payload.user_name = userName;
+ }
+ postMasqueradeOptions(courseId, payload).then(() => {
+ global.location.reload();
+ });
+ }
+
+ isSelected() {
+ const selected = this.props.selected || {};
+ const isEqual = (
+ selected.userPartitionId === (this.props.userPartitionId || null)
+ && selected.groupId === (this.props.groupId || null)
+ && selected.role === this.props.role
+ );
+ return isEqual;
+ }
+
+ render() {
+ const {
+ groupName,
+ } = this.props;
+ if (!groupName) {
+ return null;
+ }
+ const selected = this.isSelected();
+ let className;
+ if (selected) {
+ className = 'active';
+ }
+ return (
+ this.handleClick(event)}
+ >
+ {groupName}
+
+ );
+ }
+}
+MasqueradeWidgetOption.propTypes = {
+ courseId: PropTypes.string.isRequired,
+ groupId: PropTypes.number,
+ groupName: PropTypes.string.isRequired,
+ role: PropTypes.string,
+ selected: PropTypes.shape({
+ courseKey: PropTypes.string.isRequired,
+ groupId: PropTypes.number,
+ role: PropTypes.string,
+ userName: PropTypes.string,
+ userPartitionId: PropTypes.number,
+ }),
+ userName: PropTypes.string,
+ userPartitionId: PropTypes.number,
+};
+MasqueradeWidgetOption.defaultProps = {
+ groupId: null,
+ role: null,
+ selected: null,
+ userName: null,
+ userPartitionId: null,
+};
+
+export default MasqueradeWidgetOption;
diff --git a/src/courseware/course/masquerade-widget/index.js b/src/courseware/course/masquerade-widget/index.js
new file mode 100644
index 00000000..f3dcff43
--- /dev/null
+++ b/src/courseware/course/masquerade-widget/index.js
@@ -0,0 +1,3 @@
+import MasqueradeWidget from './MasqueradeWidget';
+
+export default MasqueradeWidget;
diff --git a/src/courseware/course/sequence/Unit.jsx b/src/courseware/course/sequence/Unit.jsx
index 8331c54a..1f8f874d 100644
--- a/src/courseware/course/sequence/Unit.jsx
+++ b/src/courseware/course/sequence/Unit.jsx
@@ -62,7 +62,6 @@ function Unit({
const course = useModel('courses', courseId);
const {
contentTypeGatingEnabled,
- enrollmentMode,
} = course;
// Do not remove this hook. See function description.
diff --git a/src/data/api.js b/src/data/api.js
index 38ad54f6..e721fa50 100644
--- a/src/data/api.js
+++ b/src/data/api.js
@@ -227,6 +227,18 @@ export async function getResumeBlock(courseId) {
return camelCaseObject(data);
}
+export async function getMasqueradeOptions(courseId) {
+ const url = new URL(`${getConfig().LMS_BASE_URL}/courses/${courseId}/masquerade`);
+ const { data } = await getAuthenticatedHttpClient().get(url.href, {});
+ return camelCaseObject(data);
+}
+
+export async function postMasqueradeOptions(courseId, data) {
+ const url = new URL(`${getConfig().LMS_BASE_URL}/courses/${courseId}/masquerade`);
+ const { response } = await getAuthenticatedHttpClient().post(url.href, data);
+ return camelCaseObject(response);
+}
+
export async function updateCourseDeadlines(courseId) {
const url = new URL(`${getConfig().LMS_BASE_URL}/api/course_experience/v1/reset_course_deadlines`);
await getAuthenticatedHttpClient().post(url.href, { course_key: courseId });