@openedx/frontend-app-instructor-dashboard 1.0.0-alpha.36 → 1.0.0-alpha.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
3
  import { useIntl } from '@openedx/frontend-base';
4
- import { ActionRow, Button, IconButton, Menu, MenuItem, ModalPopup, useToggle } from '@openedx/paragon';
4
+ import { ActionRow, Button, Dropdown, IconButton } from '@openedx/paragon';
5
5
  import { MoreVert } from '@openedx/paragon/icons';
6
6
  import messages from '../enrollments/messages';
7
7
  import AddBetaTestersModal from '../enrollments/components/AddBetaTestersModal';
@@ -19,12 +19,9 @@ const EnrollmentsPage = () => {
19
19
  const [isUnenrollModalOpen, setIsUnenrollModalOpen] = useState(false);
20
20
  const [isUpdateBetaTesterModalOpen, setIsUpdateBetaTesterModalOpen] = useState(false);
21
21
  const [selectedLearner, setSelectedLearner] = useState(null);
22
- const [statusMenuTarget, setStatusMenuTarget] = useState(null);
23
- const [isOpenMenu, openMenu, closeMenu] = useToggle(false);
24
22
  const { clearAlerts } = useAlert();
25
23
  const handleOpenEnrollmentStatusModal = () => {
26
24
  setIsEnrollmentStatusModalOpen(true);
27
- closeMenu();
28
25
  };
29
26
  const handleUnenroll = (learner) => {
30
27
  setIsUnenrollModalOpen(true);
@@ -56,11 +53,7 @@ const EnrollmentsPage = () => {
56
53
  setIsUpdateBetaTesterModalOpen(false);
57
54
  setSelectedLearner(null);
58
55
  };
59
- const handleStatusMenuClick = (event) => {
60
- setStatusMenuTarget(event === null || event === void 0 ? void 0 : event.currentTarget);
61
- openMenu();
62
- };
63
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "d-flex justify-content-between align-items-center", children: [_jsx("h3", { className: "text-primary-700", children: intl.formatMessage(messages.enrollmentsPageTitle) }), _jsxs(ActionRow, { children: [_jsx(IconButton, { alt: intl.formatMessage(messages.checkEnrollmentStatus), className: "lead", iconAs: MoreVert, onClick: handleStatusMenuClick }), _jsxs(Button, { variant: "outline-primary", onClick: handleAddBetaTesters, children: ["+ ", intl.formatMessage(messages.addBetaTesters)] }), _jsxs(Button, { onClick: handleEnrollLearners, children: ["+ ", intl.formatMessage(messages.enrollLearners)] })] })] }), _jsx(ModalPopup, { positionRef: statusMenuTarget, onClose: closeMenu, isOpen: isOpenMenu, children: _jsx(Menu, { children: _jsx(MenuItem, { onClick: handleOpenEnrollmentStatusModal, children: intl.formatMessage(messages.checkEnrollmentStatus) }) }) }), _jsx(AlertOutlet, {}), _jsx(EnrollmentsList, { onUnenroll: handleUnenroll, onBetaTesterChange: handleBetaTesterChange }), _jsx(EnrollmentStatusModal, { isOpen: isEnrollmentStatusModalOpen, onClose: handleCloseEnrollmentStatusModal }), selectedLearner && _jsx(UnenrollModal, { isOpen: isUnenrollModalOpen, learner: selectedLearner, onClose: handleUnenrollModalClose }), _jsx(EnrollLearnersModal, { isOpen: isEnrollLearnersModalOpen, onClose: handleCloseEnrollLearnersModal }), _jsx(AddBetaTestersModal, { isOpen: isAddBetaTestersModalOpen, onClose: () => setIsAddBetaTestersModalOpen(false) }), selectedLearner && _jsx(UpdateBetaTesterModal, { isOpen: isUpdateBetaTesterModalOpen, learner: selectedLearner, onClose: handleCloseUpdateBetaTesterModal })] }));
56
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "d-flex justify-content-between align-items-center", children: [_jsx("h3", { className: "text-primary-700", children: intl.formatMessage(messages.enrollmentsPageTitle) }), _jsxs(ActionRow, { children: [_jsxs(Dropdown, { children: [_jsx(Dropdown.Toggle, { as: IconButton, src: MoreVert, alt: intl.formatMessage(messages.checkEnrollmentStatus), id: "check-enrollment-status-menu" }), _jsx(Dropdown.Menu, { children: _jsx(Dropdown.Item, { onClick: handleOpenEnrollmentStatusModal, children: intl.formatMessage(messages.checkEnrollmentStatus) }) })] }), _jsxs(Button, { variant: "outline-primary", onClick: handleAddBetaTesters, children: ["+ ", intl.formatMessage(messages.addBetaTesters)] }), _jsxs(Button, { onClick: handleEnrollLearners, children: ["+ ", intl.formatMessage(messages.enrollLearners)] })] })] }), _jsx(AlertOutlet, {}), _jsx(EnrollmentsList, { onUnenroll: handleUnenroll, onBetaTesterChange: handleBetaTesterChange }), _jsx(EnrollmentStatusModal, { isOpen: isEnrollmentStatusModalOpen, onClose: handleCloseEnrollmentStatusModal }), selectedLearner && _jsx(UnenrollModal, { isOpen: isUnenrollModalOpen, learner: selectedLearner, onClose: handleUnenrollModalClose }), _jsx(EnrollLearnersModal, { isOpen: isEnrollLearnersModalOpen, onClose: handleCloseEnrollLearnersModal }), _jsx(AddBetaTestersModal, { isOpen: isAddBetaTestersModalOpen, onClose: () => setIsAddBetaTestersModalOpen(false) }), selectedLearner && _jsx(UpdateBetaTesterModal, { isOpen: isUpdateBetaTesterModalOpen, learner: selectedLearner, onClose: handleCloseUpdateBetaTesterModal })] }));
64
57
  };
65
58
  export default EnrollmentsPage;
66
59
  //# sourceMappingURL=EnrollmentsPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EnrollmentsPage.js","sourceRoot":"","sources":["../../src/enrollments/EnrollmentsPage.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from 'react';\nimport { useIntl } from '@openedx/frontend-base';\nimport { ActionRow, Button, IconButton, Menu, MenuItem, ModalPopup, useToggle } from '@openedx/paragon';\nimport { MoreVert } from '@openedx/paragon/icons';\nimport messages from '@src/enrollments/messages';\nimport AddBetaTestersModal from '@src/enrollments/components/AddBetaTestersModal';\nimport EnrollLearnersModal from '@src/enrollments/components/EnrollLearnersModal';\nimport EnrollmentsList from '@src/enrollments/components/EnrollmentsList';\nimport EnrollmentStatusModal from '@src/enrollments/components/EnrollmentStatusModal';\nimport UnenrollModal from '@src/enrollments/components/UnenrollModal';\nimport { EnrolledLearner } from '@src/enrollments/types';\nimport { AlertOutlet, useAlert } from '@src/providers/AlertProvider';\nimport UpdateBetaTesterModal from './components/UpdateBetaTesterModal';\n\nconst EnrollmentsPage = () => {\n const intl = useIntl();\n const [isEnrollmentStatusModalOpen, setIsEnrollmentStatusModalOpen] = useState(false);\n const [isEnrollLearnersModalOpen, setIsEnrollLearnersModalOpen] = useState(false);\n const [isAddBetaTestersModalOpen, setIsAddBetaTestersModalOpen] = useState(false);\n const [isUnenrollModalOpen, setIsUnenrollModalOpen] = useState(false);\n const [isUpdateBetaTesterModalOpen, setIsUpdateBetaTesterModalOpen] = useState(false);\n const [selectedLearner, setSelectedLearner] = useState<EnrolledLearner | null>(null);\n const [statusMenuTarget, setStatusMenuTarget] = useState<HTMLButtonElement | null>(null);\n const [isOpenMenu, openMenu, closeMenu] = useToggle(false);\n const { clearAlerts } = useAlert();\n\n const handleOpenEnrollmentStatusModal = () => {\n setIsEnrollmentStatusModalOpen(true);\n closeMenu();\n };\n\n const handleUnenroll = (learner: EnrolledLearner) => {\n setIsUnenrollModalOpen(true);\n setSelectedLearner(learner);\n };\n\n const handleUnenrollModalClose = () => {\n setIsUnenrollModalOpen(false);\n setSelectedLearner(null);\n };\n\n const handleCloseEnrollmentStatusModal = () => {\n setIsEnrollmentStatusModalOpen(false);\n };\n\n const handleEnrollLearners = () => {\n setIsEnrollLearnersModalOpen(true);\n clearAlerts();\n };\n\n const handleCloseEnrollLearnersModal = () => {\n setIsEnrollLearnersModalOpen(false);\n };\n\n const handleAddBetaTesters = () => {\n setIsAddBetaTestersModalOpen(true);\n clearAlerts();\n };\n\n const handleBetaTesterChange = (learner: EnrolledLearner) => {\n setIsUpdateBetaTesterModalOpen(true);\n setSelectedLearner(learner);\n };\n\n const handleCloseUpdateBetaTesterModal = () => {\n setIsUpdateBetaTesterModalOpen(false);\n setSelectedLearner(null);\n };\n\n const handleStatusMenuClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n setStatusMenuTarget(event?.currentTarget);\n openMenu();\n };\n\n return (\n <>\n <div className=\"d-flex justify-content-between align-items-center\">\n <h3 className=\"text-primary-700\">{intl.formatMessage(messages.enrollmentsPageTitle)}</h3>\n <ActionRow>\n <IconButton\n alt={intl.formatMessage(messages.checkEnrollmentStatus)}\n className=\"lead\"\n iconAs={MoreVert}\n onClick={handleStatusMenuClick}\n />\n <Button variant=\"outline-primary\" onClick={handleAddBetaTesters}>+ {intl.formatMessage(messages.addBetaTesters)}</Button>\n <Button onClick={handleEnrollLearners}>+ {intl.formatMessage(messages.enrollLearners)}</Button>\n </ActionRow>\n </div>\n <ModalPopup positionRef={statusMenuTarget} onClose={closeMenu} isOpen={isOpenMenu}>\n <Menu>\n <MenuItem onClick={handleOpenEnrollmentStatusModal}>\n {intl.formatMessage(messages.checkEnrollmentStatus)}\n </MenuItem>\n </Menu>\n </ModalPopup>\n <AlertOutlet />\n <EnrollmentsList onUnenroll={handleUnenroll} onBetaTesterChange={handleBetaTesterChange} />\n <EnrollmentStatusModal isOpen={isEnrollmentStatusModalOpen} onClose={handleCloseEnrollmentStatusModal} />\n {selectedLearner && <UnenrollModal isOpen={isUnenrollModalOpen} learner={selectedLearner} onClose={handleUnenrollModalClose} />}\n <EnrollLearnersModal isOpen={isEnrollLearnersModalOpen} onClose={handleCloseEnrollLearnersModal} />\n <AddBetaTestersModal isOpen={isAddBetaTestersModalOpen} onClose={() => setIsAddBetaTestersModalOpen(false)} />\n {selectedLearner && <UpdateBetaTesterModal isOpen={isUpdateBetaTesterModalOpen} learner={selectedLearner} onClose={handleCloseUpdateBetaTesterModal} />}\n </>\n );\n};\n\nexport default EnrollmentsPage;\n"]}
1
+ {"version":3,"file":"EnrollmentsPage.js","sourceRoot":"","sources":["../../src/enrollments/EnrollmentsPage.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from 'react';\nimport { useIntl } from '@openedx/frontend-base';\nimport { ActionRow, Button, Dropdown, IconButton } from '@openedx/paragon';\nimport { MoreVert } from '@openedx/paragon/icons';\nimport messages from '@src/enrollments/messages';\nimport AddBetaTestersModal from '@src/enrollments/components/AddBetaTestersModal';\nimport EnrollLearnersModal from '@src/enrollments/components/EnrollLearnersModal';\nimport EnrollmentsList from '@src/enrollments/components/EnrollmentsList';\nimport EnrollmentStatusModal from '@src/enrollments/components/EnrollmentStatusModal';\nimport UnenrollModal from '@src/enrollments/components/UnenrollModal';\nimport { EnrolledLearner } from '@src/enrollments/types';\nimport { AlertOutlet, useAlert } from '@src/providers/AlertProvider';\nimport UpdateBetaTesterModal from './components/UpdateBetaTesterModal';\n\nconst EnrollmentsPage = () => {\n const intl = useIntl();\n const [isEnrollmentStatusModalOpen, setIsEnrollmentStatusModalOpen] = useState(false);\n const [isEnrollLearnersModalOpen, setIsEnrollLearnersModalOpen] = useState(false);\n const [isAddBetaTestersModalOpen, setIsAddBetaTestersModalOpen] = useState(false);\n const [isUnenrollModalOpen, setIsUnenrollModalOpen] = useState(false);\n const [isUpdateBetaTesterModalOpen, setIsUpdateBetaTesterModalOpen] = useState(false);\n const [selectedLearner, setSelectedLearner] = useState<EnrolledLearner | null>(null);\n const { clearAlerts } = useAlert();\n\n const handleOpenEnrollmentStatusModal = () => {\n setIsEnrollmentStatusModalOpen(true);\n };\n\n const handleUnenroll = (learner: EnrolledLearner) => {\n setIsUnenrollModalOpen(true);\n setSelectedLearner(learner);\n };\n\n const handleUnenrollModalClose = () => {\n setIsUnenrollModalOpen(false);\n setSelectedLearner(null);\n };\n\n const handleCloseEnrollmentStatusModal = () => {\n setIsEnrollmentStatusModalOpen(false);\n };\n\n const handleEnrollLearners = () => {\n setIsEnrollLearnersModalOpen(true);\n clearAlerts();\n };\n\n const handleCloseEnrollLearnersModal = () => {\n setIsEnrollLearnersModalOpen(false);\n };\n\n const handleAddBetaTesters = () => {\n setIsAddBetaTestersModalOpen(true);\n clearAlerts();\n };\n\n const handleBetaTesterChange = (learner: EnrolledLearner) => {\n setIsUpdateBetaTesterModalOpen(true);\n setSelectedLearner(learner);\n };\n\n const handleCloseUpdateBetaTesterModal = () => {\n setIsUpdateBetaTesterModalOpen(false);\n setSelectedLearner(null);\n };\n\n return (\n <>\n <div className=\"d-flex justify-content-between align-items-center\">\n <h3 className=\"text-primary-700\">{intl.formatMessage(messages.enrollmentsPageTitle)}</h3>\n <ActionRow>\n <Dropdown>\n <Dropdown.Toggle\n as={IconButton}\n src={MoreVert}\n alt={intl.formatMessage(messages.checkEnrollmentStatus)}\n id=\"check-enrollment-status-menu\"\n />\n <Dropdown.Menu>\n <Dropdown.Item onClick={handleOpenEnrollmentStatusModal}>\n {intl.formatMessage(messages.checkEnrollmentStatus)}\n </Dropdown.Item>\n </Dropdown.Menu>\n </Dropdown>\n <Button variant=\"outline-primary\" onClick={handleAddBetaTesters}>+ {intl.formatMessage(messages.addBetaTesters)}</Button>\n <Button onClick={handleEnrollLearners}>+ {intl.formatMessage(messages.enrollLearners)}</Button>\n </ActionRow>\n </div>\n <AlertOutlet />\n <EnrollmentsList onUnenroll={handleUnenroll} onBetaTesterChange={handleBetaTesterChange} />\n <EnrollmentStatusModal isOpen={isEnrollmentStatusModalOpen} onClose={handleCloseEnrollmentStatusModal} />\n {selectedLearner && <UnenrollModal isOpen={isUnenrollModalOpen} learner={selectedLearner} onClose={handleUnenrollModalClose} />}\n <EnrollLearnersModal isOpen={isEnrollLearnersModalOpen} onClose={handleCloseEnrollLearnersModal} />\n <AddBetaTestersModal isOpen={isAddBetaTestersModalOpen} onClose={() => setIsAddBetaTestersModalOpen(false)} />\n {selectedLearner && <UpdateBetaTesterModal isOpen={isUpdateBetaTesterModalOpen} learner={selectedLearner} onClose={handleCloseUpdateBetaTesterModal} />}\n </>\n );\n};\n\nexport default EnrollmentsPage;\n"]}
@@ -1,6 +1,15 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
11
  import { useParams } from 'react-router-dom';
3
- import { useCallback, useEffect } from 'react';
12
+ import { useCallback, useEffect, useRef } from 'react';
4
13
  import { useIntl } from '@openedx/frontend-base';
5
14
  import { Button, ModalDialog } from '@openedx/paragon';
6
15
  import { useAlert } from '../../providers/AlertProvider';
@@ -9,44 +18,47 @@ import messages from '../../enrollments/messages';
9
18
  const UpdateBetaTesterModal = ({ learner, isOpen, onClose }) => {
10
19
  const intl = useIntl();
11
20
  const { courseId = '' } = useParams();
12
- const { mutate: updateBetaTester, isPending } = useUpdateBetaTesters(courseId);
21
+ // Using mutateAsync avoids mutate callbacks being discarded on useEffect re-runs
22
+ const { mutateAsync: updateBetaTester, isPending } = useUpdateBetaTesters(courseId);
13
23
  const { addAlert, showModal } = useAlert();
14
- const handleUpdateBetaTester = useCallback(() => {
15
- updateBetaTester({
16
- identifier: [learner.username],
17
- action: learner.isBetaTester ? 'remove' : 'add',
18
- }, {
19
- onSuccess: (data) => {
20
- var _a, _b;
21
- const failedUsernames = ((_a = data.results) === null || _a === void 0 ? void 0 : _a.filter(user => user.userDoesNotExist).map(user => user.identifier)) || [];
22
- const inactiveUsernames = ((_b = data.results) === null || _b === void 0 ? void 0 : _b.filter(user => !user.isActive && user.isActive !== null && !user.userDoesNotExist).map(user => user.identifier)) || [];
23
- if (failedUsernames.length > 0) {
24
- addAlert({
25
- type: 'danger',
26
- message: intl.formatMessage(messages.failedBetaTesters),
27
- extraContent: (failedUsernames.map((learner) => (_jsxs("p", { className: "mb-0", children: ["\u2022 ", intl.formatMessage(messages.unknownLearner, { learner })] }, learner))))
28
- });
29
- }
30
- if (inactiveUsernames.length > 0) {
31
- addAlert({
32
- type: 'warning',
33
- message: intl.formatMessage(messages.inactiveUsers),
34
- extraContent: (inactiveUsernames.map((learner) => (_jsxs("p", { className: "mb-0", children: ["\u2022 ", intl.formatMessage(messages.inactiveLearner, { learner })] }, learner))))
35
- });
36
- }
37
- },
38
- onError: () => {
39
- showModal({
40
- message: learner.isBetaTester ? intl.formatMessage(messages.removeBetaTesterError) : intl.formatMessage(messages.addBetaTesterError),
41
- variant: 'danger',
42
- confirmText: intl.formatMessage(messages.closeButton),
24
+ // Avoid duplicate calls to mutate
25
+ const hasFired = useRef(false);
26
+ const handleUpdateBetaTester = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
27
+ var _a, _b;
28
+ try {
29
+ const data = yield updateBetaTester({
30
+ identifier: [learner.username],
31
+ action: learner.isBetaTester ? 'remove' : 'add',
32
+ });
33
+ const failedUsernames = ((_a = data.results) === null || _a === void 0 ? void 0 : _a.filter(user => user.userDoesNotExist).map(user => user.identifier)) || [];
34
+ const inactiveUsernames = ((_b = data.results) === null || _b === void 0 ? void 0 : _b.filter(user => !user.isActive && user.isActive !== null && !user.userDoesNotExist).map(user => user.identifier)) || [];
35
+ if (failedUsernames.length > 0) {
36
+ addAlert({
37
+ type: 'danger',
38
+ message: intl.formatMessage(messages.failedBetaTesters),
39
+ extraContent: (failedUsernames.map((learner) => (_jsxs("p", { className: "mb-0", children: ["\u2022 ", intl.formatMessage(messages.unknownLearner, { learner })] }, learner))))
40
+ });
41
+ }
42
+ if (inactiveUsernames.length > 0) {
43
+ addAlert({
44
+ type: 'warning',
45
+ message: intl.formatMessage(messages.inactiveUsers),
46
+ extraContent: (inactiveUsernames.map((learner) => (_jsxs("p", { className: "mb-0", children: ["\u2022 ", intl.formatMessage(messages.inactiveLearner, { learner })] }, learner))))
43
47
  });
44
48
  }
45
- });
46
- onClose();
47
- }, [updateBetaTester, learner.username, learner.isBetaTester, addAlert, intl, showModal, onClose]);
49
+ onClose();
50
+ }
51
+ catch (_c) {
52
+ showModal({
53
+ message: learner.isBetaTester ? intl.formatMessage(messages.removeBetaTesterError) : intl.formatMessage(messages.addBetaTesterError),
54
+ variant: 'danger',
55
+ confirmText: intl.formatMessage(messages.closeButton),
56
+ });
57
+ }
58
+ }), [updateBetaTester, learner, addAlert, intl, showModal, onClose]);
48
59
  useEffect(() => {
49
- if (isOpen && !learner.isBetaTester) {
60
+ if (isOpen && !learner.isBetaTester && !hasFired.current) {
61
+ hasFired.current = true;
50
62
  handleUpdateBetaTester();
51
63
  }
52
64
  }, [handleUpdateBetaTester, isOpen, learner.isBetaTester]);
@@ -1 +1 @@
1
- {"version":3,"file":"UpdateBetaTesterModal.js","sourceRoot":"","sources":["../../../src/enrollments/components/UpdateBetaTesterModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useParams } from 'react-router-dom';\nimport { useCallback, useEffect } from 'react';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Button, ModalDialog } from '@openedx/paragon';\nimport { useAlert } from '@src/providers/AlertProvider';\nimport { useUpdateBetaTesters } from '@src/enrollments/data/apiHook';\nimport messages from '@src/enrollments/messages';\nimport { EnrolledLearner } from '@src/enrollments/types';\n\ninterface UpdateBetaTesterModalProps {\n learner: EnrolledLearner,\n isOpen: boolean,\n onClose: () => void,\n}\n\nconst UpdateBetaTesterModal = ({ learner, isOpen, onClose }: UpdateBetaTesterModalProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const { mutate: updateBetaTester, isPending } = useUpdateBetaTesters(courseId);\n const { addAlert, showModal } = useAlert();\n\n const handleUpdateBetaTester = useCallback(() => {\n updateBetaTester({\n identifier: [learner.username],\n action: learner.isBetaTester ? 'remove' : 'add',\n }, {\n onSuccess: (data) => {\n const failedUsernames = data.results?.filter(user => user.userDoesNotExist).map(user => user.identifier) || [];\n const inactiveUsernames = data.results?.filter(user => !user.isActive && user.isActive !== null && !user.userDoesNotExist).map(user => user.identifier) || [];\n if (failedUsernames.length > 0) {\n addAlert({\n type: 'danger',\n message: intl.formatMessage(messages.failedBetaTesters),\n extraContent: (\n failedUsernames.map((learner: string) => (\n <p key={learner} className=\"mb-0\">• {intl.formatMessage(messages.unknownLearner, { learner })}</p>\n ))\n )\n });\n }\n if (inactiveUsernames.length > 0) {\n addAlert({\n type: 'warning',\n message: intl.formatMessage(messages.inactiveUsers),\n extraContent: (\n inactiveUsernames.map((learner: string) => (\n <p key={learner} className=\"mb-0\">• {intl.formatMessage(messages.inactiveLearner, { learner })}</p>\n ))\n )\n });\n }\n },\n onError: () => {\n showModal({\n message: learner.isBetaTester ? intl.formatMessage(messages.removeBetaTesterError) : intl.formatMessage(messages.addBetaTesterError),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n\n onClose();\n }, [updateBetaTester, learner.username, learner.isBetaTester, addAlert, intl, showModal, onClose]);\n\n useEffect(() => {\n if (isOpen && !learner.isBetaTester) {\n handleUpdateBetaTester();\n }\n }, [handleUpdateBetaTester, isOpen, learner.isBetaTester]);\n\n // Only show modal for removing beta testers (requires confirmation)\n if (!isOpen || !learner.isBetaTester) {\n return null;\n }\n\n return (\n <ModalDialog isOpen={isOpen} onClose={onClose} title={intl.formatMessage(messages.removeBetaTesterTitle)} isOverflowVisible={false}>\n <ModalDialog.Header>\n <h3 className=\"text-primary-500\">{intl.formatMessage(messages.removeBetaTesterTitle)}</h3>\n </ModalDialog.Header>\n <ModalDialog.Body className=\"py-4\">\n <p>{intl.formatMessage(messages.removeBetaTesterDescription)}</p>\n </ModalDialog.Body>\n <ModalDialog.Footer>\n <Button variant=\"tertiary\" onClick={onClose}>{intl.formatMessage(messages.cancelButton)}</Button>\n <Button\n className=\"ml-2\"\n onClick={handleUpdateBetaTester}\n disabled={isPending}\n >\n {intl.formatMessage(messages.revoke)}\n </Button>\n </ModalDialog.Footer>\n </ModalDialog>\n );\n};\n\nexport default UpdateBetaTesterModal;\n"]}
1
+ {"version":3,"file":"UpdateBetaTesterModal.js","sourceRoot":"","sources":["../../../src/enrollments/components/UpdateBetaTesterModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useParams } from 'react-router-dom';\nimport { useCallback, useEffect, useRef } from 'react';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Button, ModalDialog } from '@openedx/paragon';\nimport { useAlert } from '@src/providers/AlertProvider';\nimport { useUpdateBetaTesters } from '@src/enrollments/data/apiHook';\nimport messages from '@src/enrollments/messages';\nimport { EnrolledLearner } from '@src/enrollments/types';\n\ninterface UpdateBetaTesterModalProps {\n learner: EnrolledLearner,\n isOpen: boolean,\n onClose: () => void,\n}\n\nconst UpdateBetaTesterModal = ({ learner, isOpen, onClose }: UpdateBetaTesterModalProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n // Using mutateAsync avoids mutate callbacks being discarded on useEffect re-runs\n const { mutateAsync: updateBetaTester, isPending } = useUpdateBetaTesters(courseId);\n const { addAlert, showModal } = useAlert();\n // Avoid duplicate calls to mutate\n const hasFired = useRef(false);\n\n const handleUpdateBetaTester = useCallback(async () => {\n try {\n const data = await updateBetaTester({\n identifier: [learner.username],\n action: learner.isBetaTester ? 'remove' : 'add',\n });\n const failedUsernames = data.results?.filter(user => user.userDoesNotExist).map(user => user.identifier) || [];\n const inactiveUsernames = data.results?.filter(user => !user.isActive && user.isActive !== null && !user.userDoesNotExist).map(user => user.identifier) || [];\n if (failedUsernames.length > 0) {\n addAlert({\n type: 'danger',\n message: intl.formatMessage(messages.failedBetaTesters),\n extraContent: (\n failedUsernames.map((learner: string) => (\n <p key={learner} className=\"mb-0\">• {intl.formatMessage(messages.unknownLearner, { learner })}</p>\n ))\n )\n });\n }\n if (inactiveUsernames.length > 0) {\n addAlert({\n type: 'warning',\n message: intl.formatMessage(messages.inactiveUsers),\n extraContent: (\n inactiveUsernames.map((learner: string) => (\n <p key={learner} className=\"mb-0\">• {intl.formatMessage(messages.inactiveLearner, { learner })}</p>\n ))\n )\n });\n }\n onClose();\n } catch {\n showModal({\n message: learner.isBetaTester ? intl.formatMessage(messages.removeBetaTesterError) : intl.formatMessage(messages.addBetaTesterError),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n }, [updateBetaTester, learner, addAlert, intl, showModal, onClose]);\n\n useEffect(() => {\n if (isOpen && !learner.isBetaTester && !hasFired.current) {\n hasFired.current = true;\n handleUpdateBetaTester();\n }\n }, [handleUpdateBetaTester, isOpen, learner.isBetaTester]);\n\n // Only show modal for removing beta testers (requires confirmation)\n if (!isOpen || !learner.isBetaTester) {\n return null;\n }\n\n return (\n <ModalDialog isOpen={isOpen} onClose={onClose} title={intl.formatMessage(messages.removeBetaTesterTitle)} isOverflowVisible={false}>\n <ModalDialog.Header>\n <h3 className=\"text-primary-500\">{intl.formatMessage(messages.removeBetaTesterTitle)}</h3>\n </ModalDialog.Header>\n <ModalDialog.Body className=\"py-4\">\n <p>{intl.formatMessage(messages.removeBetaTesterDescription)}</p>\n </ModalDialog.Body>\n <ModalDialog.Footer>\n <Button variant=\"tertiary\" onClick={onClose}>{intl.formatMessage(messages.cancelButton)}</Button>\n <Button\n className=\"ml-2\"\n onClick={handleUpdateBetaTester}\n disabled={isPending}\n >\n {intl.formatMessage(messages.revoke)}\n </Button>\n </ModalDialog.Footer>\n </ModalDialog>\n );\n};\n\nexport default UpdateBetaTesterModal;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openedx/frontend-app-instructor-dashboard",
3
- "version": "1.0.0-alpha.36",
3
+ "version": "1.0.0-alpha.37",
4
4
  "description": "The Open edX Instructor Dashboard",
5
5
  "repository": {
6
6
  "type": "git",