@openedx/frontend-app-instructor-dashboard 1.0.0-alpha.33 → 1.0.0-alpha.34

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.
Files changed (32) hide show
  1. package/dist/components/SpecifyLearnerField.js +25 -5
  2. package/dist/components/SpecifyLearnerField.js.map +1 -1
  3. package/dist/components/SpecifyProblemField.js +2 -2
  4. package/dist/components/SpecifyProblemField.js.map +1 -1
  5. package/dist/components/messages.d.ts +5 -0
  6. package/dist/components/messages.js +5 -0
  7. package/dist/components/messages.js.map +1 -1
  8. package/dist/enrollments/components/UpdateBetaTesterModal.js +9 -1
  9. package/dist/enrollments/components/UpdateBetaTesterModal.js.map +1 -1
  10. package/dist/grading/components/GradingLearnerContent.js +4 -0
  11. package/dist/grading/components/GradingLearnerContent.js.map +1 -1
  12. package/dist/slots/CourseInfoSlot/CourseInfoSlot.d.ts +2 -0
  13. package/dist/slots/CourseInfoSlot/CourseInfoSlot.js +14 -0
  14. package/dist/slots/CourseInfoSlot/CourseInfoSlot.js.map +1 -0
  15. package/dist/slots.js +9 -1
  16. package/dist/slots.js.map +1 -1
  17. package/dist/specialExams/components/AllowancesList.js +9 -4
  18. package/dist/specialExams/components/AllowancesList.js.map +1 -1
  19. package/dist/specialExams/components/AttemptsList.js +9 -4
  20. package/dist/specialExams/components/AttemptsList.js.map +1 -1
  21. package/dist/specialExams/components/EditAllowanceModal.js +1 -1
  22. package/dist/specialExams/components/EditAllowanceModal.js.map +1 -1
  23. package/dist/specialExams/data/api.js +6 -0
  24. package/dist/specialExams/data/api.js.map +1 -1
  25. package/dist/specialExams/data/queryKeys.d.ts +2 -2
  26. package/dist/specialExams/data/queryKeys.js +2 -2
  27. package/dist/specialExams/data/queryKeys.js.map +1 -1
  28. package/dist/specialExams/types.d.ts +1 -0
  29. package/dist/specialExams/types.js.map +1 -1
  30. package/dist/types/index.d.ts +4 -0
  31. package/dist/types/index.js.map +1 -1
  32. package/package.json +1 -1
@@ -8,6 +8,23 @@ import { SpinnerIcon } from '@openedx/paragon/icons';
8
8
  import { useDebouncedFilter } from '../hooks/useDebouncedFilter';
9
9
  import { useCourseInfo, useLearner } from '../data/apiHook';
10
10
  import messages from './messages';
11
+ const errorMessages = {
12
+ not_found: messages.learnerNotFound,
13
+ generic_error: messages.learnerGenericError,
14
+ not_enrolled: messages.learnerNotEnrolled,
15
+ };
16
+ const getErrorState = (error, data) => {
17
+ var _a, _b;
18
+ const isNotFoundError = isAxiosError(error)
19
+ && (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 404 || ((_b = error.response) === null || _b === void 0 ? void 0 : _b.status) === 400);
20
+ if (isNotFoundError)
21
+ return 'not_found';
22
+ if (data && !data.isEnrolled)
23
+ return 'not_enrolled';
24
+ if (error && !isNotFoundError)
25
+ return 'generic_error';
26
+ return null;
27
+ };
11
28
  const initialLearnerState = {
12
29
  username: '',
13
30
  fullName: '',
@@ -15,22 +32,23 @@ const initialLearnerState = {
15
32
  isEnrolled: false,
16
33
  };
17
34
  const SpecifyLearnerField = forwardRef(({ learner, onClickSelect }, ref) => {
18
- var _a;
19
35
  const intl = useIntl();
20
36
  const { courseId = '' } = useParams();
21
37
  const [identifier, setIdentifier] = useState('');
22
38
  const [showLearner, enableShowLearner, disableShowLearner] = useToggle(!!learner);
39
+ const [errorState, setErrorState] = useState(null);
23
40
  const { data: courseInfo } = useCourseInfo(courseId);
24
41
  const permissions = (courseInfo === null || courseInfo === void 0 ? void 0 : courseInfo.permissions) || { admin: false, dataResearcher: false };
25
42
  const { inputValue, handleChange, resetFilter } = useDebouncedFilter({
26
43
  filterValue: identifier,
27
44
  setFilter: setIdentifier,
28
45
  });
29
- const { data, refetch, error } = useLearner(courseId, inputValue);
46
+ const { data, refetch } = useLearner(courseId, inputValue);
30
47
  const resetState = () => {
31
48
  resetFilter();
32
49
  onClickSelect('');
33
50
  disableShowLearner();
51
+ setErrorState(null);
34
52
  };
35
53
  useImperativeHandle(ref, () => ({
36
54
  reset: resetState,
@@ -38,6 +56,9 @@ const SpecifyLearnerField = forwardRef(({ learner, onClickSelect }, ref) => {
38
56
  const selectedLearner = learner || data || initialLearnerState;
39
57
  const handleInputChange = (event) => {
40
58
  handleChange(event.target.value);
59
+ if (errorState) {
60
+ setErrorState(null);
61
+ }
41
62
  if (showLearner) {
42
63
  disableShowLearner();
43
64
  }
@@ -49,15 +70,14 @@ const SpecifyLearnerField = forwardRef(({ learner, onClickSelect }, ref) => {
49
70
  // Need to pass empty value if learner is not valid to clear out any previously selected learner
50
71
  // We could have other conditions/fields depending on valid learner
51
72
  const formValue = !result.error && ((_a = result.data) === null || _a === void 0 ? void 0 : _a.isEnrolled) ? inputValue : '';
73
+ setErrorState(getErrorState(result.error, result === null || result === void 0 ? void 0 : result.data));
52
74
  onClickSelect(formValue);
53
75
  enableShowLearner();
54
76
  });
55
77
  }
56
78
  };
57
79
  return (_jsxs(FormGroup, { className: "mb-0", size: "sm", children: [_jsx(FormLabel, { className: "text-primary-500 d-flex", children: selectedLearner.username ? intl.formatMessage(messages.selectedLearner) : intl.formatMessage(messages.specifyLearner) }), _jsxs("div", { className: "d-flex align-items-center", children: [_jsx(FormControl, { className: `mr-2 ${selectedLearner.username && showLearner ? 'd-none' : ''}`, name: "emailOrUsername", placeholder: intl.formatMessage(messages.specifyLearnerPlaceholder), size: "md", autoResize: true, value: inputValue, onChange: handleInputChange }), selectedLearner.username && showLearner ? (_jsxs(_Fragment, { children: [_jsx(Avatar, { className: "mr-2.5", size: "sm" }), _jsxs("div", { className: "d-flex flex-column mr-3 text-primary-500", children: [_jsx("p", { className: "mb-0", children: selectedLearner.username }), (permissions.admin || permissions.dataResearcher)
58
- && (_jsxs("div", { className: "d-flex x-small", children: [_jsx("p", { className: "mr-3 mb-0", children: selectedLearner.fullName }), _jsx("p", { className: "mb-0", children: selectedLearner.email })] }))] }), !learner && _jsx(Button, { iconBefore: SpinnerIcon, onClick: resetState, children: intl.formatMessage(messages.change) })] })) : (_jsx(Button, { onClick: handleClickSelect, disabled: !inputValue, children: intl.formatMessage(messages.select) }))] }), showLearner && error
59
- && isAxiosError(error)
60
- && ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 404 && (_jsx("p", { className: "text-danger-500 mb-0 x-small mt-2", children: intl.formatMessage(messages.learnerNotFound, { identifier }) })), showLearner && !error && !(selectedLearner === null || selectedLearner === void 0 ? void 0 : selectedLearner.isEnrolled) && (_jsx("p", { className: "text-danger-500 mb-0 x-small mt-2", children: intl.formatMessage(messages.learnerNotEnrolled, { identifier }) }))] }));
80
+ && (_jsxs("div", { className: "d-flex x-small", children: [_jsx("p", { className: "mr-3 mb-0", children: selectedLearner.fullName }), _jsx("p", { className: "mb-0", children: selectedLearner.email })] }))] }), !learner && _jsx(Button, { iconBefore: SpinnerIcon, onClick: resetState, children: intl.formatMessage(messages.change) })] })) : (_jsx(Button, { onClick: handleClickSelect, disabled: !inputValue, children: intl.formatMessage(messages.select) }))] }), showLearner && errorState && (_jsx("p", { className: "text-danger-500 mb-0 x-small mt-2", children: intl.formatMessage(errorMessages[errorState], { identifier: inputValue }) }))] }));
61
81
  });
62
82
  SpecifyLearnerField.displayName = 'SpecifyLearnerField';
63
83
  export default SpecifyLearnerField;
@@ -1 +1 @@
1
- {"version":3,"file":"SpecifyLearnerField.js","sourceRoot":"","sources":["../../src/components/SpecifyLearnerField.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState, ChangeEvent, useImperativeHandle, forwardRef } from 'react';\nimport { isAxiosError } from 'axios';\nimport { useParams } from 'react-router-dom';\nimport { Avatar, Button, FormControl, FormGroup, FormLabel, useToggle } from '@openedx/paragon';\nimport { useIntl } from '@openedx/frontend-base';\nimport { SpinnerIcon } from '@openedx/paragon/icons';\nimport { useDebouncedFilter } from '@src/hooks/useDebouncedFilter';\nimport { useCourseInfo, useLearner } from '@src/data/apiHook';\nimport { SelectedLearner } from '@src/types';\nimport messages from './messages';\n\ninterface SpecifyLearnerFieldProps {\n learner?: SelectedLearner,\n onClickSelect: (emailOrUsername: string) => void,\n}\n\ninterface SpecifyLearnerFieldRef {\n reset: () => void,\n}\n\nconst initialLearnerState = {\n username: '',\n fullName: '',\n email: '',\n isEnrolled: false,\n};\n\nconst SpecifyLearnerField = forwardRef<SpecifyLearnerFieldRef, SpecifyLearnerFieldProps>(({ learner, onClickSelect }, ref) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [identifier, setIdentifier] = useState('');\n const [showLearner, enableShowLearner, disableShowLearner] = useToggle(!!learner);\n const { data: courseInfo } = useCourseInfo(courseId);\n const permissions = courseInfo?.permissions || { admin: false, dataResearcher: false };\n const { inputValue, handleChange, resetFilter } = useDebouncedFilter({\n filterValue: identifier,\n setFilter: setIdentifier,\n });\n const { data, refetch, error } = useLearner(courseId, inputValue);\n\n const resetState = () => {\n resetFilter();\n onClickSelect('');\n disableShowLearner();\n };\n\n useImperativeHandle(ref, () => ({\n reset: resetState,\n }));\n\n const selectedLearner = learner || data || initialLearnerState;\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n handleChange(event.target.value);\n\n if (showLearner) {\n disableShowLearner();\n }\n };\n\n const handleClickSelect = () => {\n if (inputValue) {\n refetch().then((result) => {\n // Need to pass empty value if learner is not valid to clear out any previously selected learner\n // We could have other conditions/fields depending on valid learner\n const formValue = !result.error && result.data?.isEnrolled ? inputValue : '';\n onClickSelect(formValue);\n enableShowLearner();\n });\n }\n };\n\n return (\n <FormGroup className=\"mb-0\" size=\"sm\">\n <FormLabel className=\"text-primary-500 d-flex\">{selectedLearner.username ? intl.formatMessage(messages.selectedLearner) : intl.formatMessage(messages.specifyLearner)}</FormLabel>\n <div className=\"d-flex align-items-center\">\n <FormControl\n className={`mr-2 ${selectedLearner.username && showLearner ? 'd-none' : ''}`}\n name=\"emailOrUsername\"\n placeholder={intl.formatMessage(messages.specifyLearnerPlaceholder)}\n size=\"md\"\n autoResize\n value={inputValue}\n onChange={handleInputChange}\n />\n {selectedLearner.username && showLearner ? (\n <>\n <Avatar className=\"mr-2.5\" size=\"sm\" />\n <div className=\"d-flex flex-column mr-3 text-primary-500\">\n <p className=\"mb-0\">{selectedLearner.username}</p>\n {(permissions.admin || permissions.dataResearcher)\n && (\n <div className=\"d-flex x-small\">\n <p className=\"mr-3 mb-0\">{selectedLearner.fullName}</p>\n <p className=\"mb-0\">{selectedLearner.email}</p>\n </div>\n )}\n </div>\n {!learner && <Button iconBefore={SpinnerIcon} onClick={resetState}>{intl.formatMessage(messages.change)}</Button>}\n </>\n ) : (\n <Button onClick={handleClickSelect} disabled={!inputValue}>{intl.formatMessage(messages.select)}</Button>\n )}\n </div>\n {showLearner && error\n && isAxiosError(error)\n && error.response?.status === 404 && (\n <p className=\"text-danger-500 mb-0 x-small mt-2\">\n {intl.formatMessage(messages.learnerNotFound, { identifier })}\n </p>\n )}\n {\n showLearner && !error && !selectedLearner?.isEnrolled && (\n <p className=\"text-danger-500 mb-0 x-small mt-2\">\n {intl.formatMessage(messages.learnerNotEnrolled, { identifier })}\n </p>\n )\n }\n </FormGroup>\n );\n});\n\nSpecifyLearnerField.displayName = 'SpecifyLearnerField';\n\nexport default SpecifyLearnerField;\n"]}
1
+ {"version":3,"file":"SpecifyLearnerField.js","sourceRoot":"","sources":["../../src/components/SpecifyLearnerField.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState, ChangeEvent, useImperativeHandle, forwardRef } from 'react';\nimport { isAxiosError } from 'axios';\nimport { useParams } from 'react-router-dom';\nimport { Avatar, Button, FormControl, FormGroup, FormLabel, useToggle } from '@openedx/paragon';\nimport { useIntl } from '@openedx/frontend-base';\nimport { SpinnerIcon } from '@openedx/paragon/icons';\nimport { useDebouncedFilter } from '@src/hooks/useDebouncedFilter';\nimport { useCourseInfo, useLearner } from '@src/data/apiHook';\nimport { SelectedLearner } from '@src/types';\nimport messages from './messages';\n\ninterface SpecifyLearnerFieldProps {\n learner?: SelectedLearner,\n onClickSelect: (emailOrUsername: string) => void,\n}\n\ninterface SpecifyLearnerFieldRef {\n reset: () => void,\n}\n\ntype ErrorState = 'not_enrolled' | 'not_found' | 'generic_error' | null;\n\nconst errorMessages = {\n not_found: messages.learnerNotFound,\n generic_error: messages.learnerGenericError,\n not_enrolled: messages.learnerNotEnrolled,\n};\n\nconst getErrorState = (error: Error | null, data?: SelectedLearner): ErrorState => {\n const isNotFoundError = isAxiosError(error)\n && (error.response?.status === 404 || error.response?.status === 400);\n\n if (isNotFoundError) return 'not_found';\n if (data && !data.isEnrolled) return 'not_enrolled';\n if (error && !isNotFoundError) return 'generic_error';\n return null;\n};\n\nconst initialLearnerState = {\n username: '',\n fullName: '',\n email: '',\n isEnrolled: false,\n};\n\nconst SpecifyLearnerField = forwardRef<SpecifyLearnerFieldRef, SpecifyLearnerFieldProps>(({ learner, onClickSelect }, ref) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [identifier, setIdentifier] = useState('');\n const [showLearner, enableShowLearner, disableShowLearner] = useToggle(!!learner);\n const [errorState, setErrorState] = useState<ErrorState>(null);\n const { data: courseInfo } = useCourseInfo(courseId);\n const permissions = courseInfo?.permissions || { admin: false, dataResearcher: false };\n const { inputValue, handleChange, resetFilter } = useDebouncedFilter({\n filterValue: identifier,\n setFilter: setIdentifier,\n });\n const { data, refetch } = useLearner(courseId, inputValue);\n\n const resetState = () => {\n resetFilter();\n onClickSelect('');\n disableShowLearner();\n setErrorState(null);\n };\n\n useImperativeHandle(ref, () => ({\n reset: resetState,\n }));\n\n const selectedLearner = learner || data || initialLearnerState;\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n handleChange(event.target.value);\n\n if (errorState) {\n setErrorState(null);\n }\n\n if (showLearner) {\n disableShowLearner();\n }\n };\n\n const handleClickSelect = () => {\n if (inputValue) {\n refetch().then((result) => {\n // Need to pass empty value if learner is not valid to clear out any previously selected learner\n // We could have other conditions/fields depending on valid learner\n const formValue = !result.error && result.data?.isEnrolled ? inputValue : '';\n\n setErrorState(getErrorState(result.error, result?.data));\n onClickSelect(formValue);\n enableShowLearner();\n });\n }\n };\n\n return (\n <FormGroup className=\"mb-0\" size=\"sm\">\n <FormLabel className=\"text-primary-500 d-flex\">{selectedLearner.username ? intl.formatMessage(messages.selectedLearner) : intl.formatMessage(messages.specifyLearner)}</FormLabel>\n <div className=\"d-flex align-items-center\">\n <FormControl\n className={`mr-2 ${selectedLearner.username && showLearner ? 'd-none' : ''}`}\n name=\"emailOrUsername\"\n placeholder={intl.formatMessage(messages.specifyLearnerPlaceholder)}\n size=\"md\"\n autoResize\n value={inputValue}\n onChange={handleInputChange}\n />\n {selectedLearner.username && showLearner ? (\n <>\n <Avatar className=\"mr-2.5\" size=\"sm\" />\n <div className=\"d-flex flex-column mr-3 text-primary-500\">\n <p className=\"mb-0\">{selectedLearner.username}</p>\n {(permissions.admin || permissions.dataResearcher)\n && (\n <div className=\"d-flex x-small\">\n <p className=\"mr-3 mb-0\">{selectedLearner.fullName}</p>\n <p className=\"mb-0\">{selectedLearner.email}</p>\n </div>\n )}\n </div>\n {!learner && <Button iconBefore={SpinnerIcon} onClick={resetState}>{intl.formatMessage(messages.change)}</Button>}\n </>\n ) : (\n <Button onClick={handleClickSelect} disabled={!inputValue}>{intl.formatMessage(messages.select)}</Button>\n )}\n </div>\n {showLearner && errorState && (\n <p className=\"text-danger-500 mb-0 x-small mt-2\">\n {intl.formatMessage(errorMessages[errorState], { identifier: inputValue })}\n </p>\n )}\n </FormGroup>\n );\n});\n\nSpecifyLearnerField.displayName = 'SpecifyLearnerField';\n\nexport default SpecifyLearnerField;\n"]}
@@ -9,7 +9,7 @@ import messages from './messages';
9
9
  import { useDebouncedFilter } from '../hooks/useDebouncedFilter';
10
10
  import { useProblemDetails } from '../data/apiHook';
11
11
  const SpecifyProblemField = forwardRef(({ buttonLabel, disabled, fieldLabel, problemResponsesError, usernameOrEmail = '', onClickSelect, }, ref) => {
12
- var _a;
12
+ var _a, _b;
13
13
  const intl = useIntl();
14
14
  const { courseId = '' } = useParams();
15
15
  const [problemLocation, setProblemLocation] = useState('');
@@ -45,7 +45,7 @@ const SpecifyProblemField = forwardRef(({ buttonLabel, disabled, fieldLabel, pro
45
45
  .map(breadcrumb => breadcrumb.displayName)
46
46
  .join(' > ') }), _jsx("p", { className: "text-primary-500 mb-0", children: data.name }), _jsx("p", { className: "x-small text-gray-700 text-truncate mb-0", children: data.id })] }), _jsx(Button, { iconBefore: SpinnerIcon, onClick: disableShowSelectedLocation, children: intl.formatMessage(messages.change) })] })) : (_jsxs(_Fragment, { children: [_jsx(Form.Control, { type: "text", placeholder: intl.formatMessage(messages.problemLocationPlaceholder), value: inputValue, onChange: handleInputChange, className: "flex-grow-1", size: "md" }), problemResponsesError && (_jsx(Form.Control.Feedback, { type: "invalid", children: problemResponsesError })), _jsx(Button, { variant: "primary", onClick: handleClick, disabled: disabled || !inputValue, className: "text-nowrap", children: buttonLabel })] })) }), showSelectedLocation && error
47
47
  && isAxiosError(error)
48
- && (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 400) && (_jsx("p", { className: "text-danger-500 mb-0 x-small mt-2", children: intl.formatMessage(messages.problemNotFound, { identifier: inputValue }) }))] }));
48
+ && ((((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 400) || (((_b = error.response) === null || _b === void 0 ? void 0 : _b.status) === 404)) && (_jsx("p", { className: "text-danger-500 mb-0 x-small mt-2", children: intl.formatMessage(messages.problemNotFound, { identifier: inputValue }) }))] }));
49
49
  });
50
50
  SpecifyProblemField.displayName = 'SpecifyProblemField';
51
51
  export default SpecifyProblemField;
@@ -1 +1 @@
1
- {"version":3,"file":"SpecifyProblemField.js","sourceRoot":"","sources":["../../src/components/SpecifyProblemField.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState, useImperativeHandle, forwardRef } from 'react';\nimport { isAxiosError } from 'axios';\nimport { useParams } from 'react-router-dom';\nimport { Button, Form, Icon, OverlayTrigger, Tooltip, useToggle } from '@openedx/paragon';\nimport { InfoOutline, SpinnerIcon } from '@openedx/paragon/icons';\nimport { useIntl } from '@openedx/frontend-base';\nimport messages from './messages';\nimport { useDebouncedFilter } from '@src/hooks/useDebouncedFilter';\nimport { useProblemDetails } from '@src/data/apiHook';\n\ninterface SpecifyProblemFieldProps {\n buttonLabel: string,\n disabled?: boolean,\n fieldLabel: string,\n problemResponsesError?: string,\n usernameOrEmail?: string,\n onClickSelect: (problemLocation: string, event: React.MouseEvent<HTMLButtonElement>) => void,\n}\n\ninterface SpecifyProblemFieldRef {\n reset: () => void,\n}\n\nconst SpecifyProblemField = forwardRef<SpecifyProblemFieldRef, SpecifyProblemFieldProps>(({\n buttonLabel,\n disabled,\n fieldLabel,\n problemResponsesError,\n usernameOrEmail = '',\n onClickSelect,\n}, ref) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [problemLocation, setProblemLocation] = useState('');\n const [showSelectedLocation, enableShowSelectedLocation, disableShowSelectedLocation] = useToggle(false);\n\n const { inputValue, handleChange, resetFilter } = useDebouncedFilter({\n filterValue: problemLocation,\n setFilter: setProblemLocation,\n });\n const { data = { breadcrumbs: [], name: '', id: '' }, refetch, error } = useProblemDetails(courseId, inputValue, usernameOrEmail);\n\n useImperativeHandle(ref, () => ({\n reset: () => {\n resetFilter();\n disableShowSelectedLocation();\n }\n }));\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n handleChange(e.target.value);\n\n if (showSelectedLocation) {\n disableShowSelectedLocation();\n }\n };\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (inputValue) {\n refetch().then(() => {\n onClickSelect(inputValue, event);\n enableShowSelectedLocation();\n });\n }\n };\n\n return (\n <Form.Group className=\"mb-0\" isInvalid={!!problemResponsesError} size=\"sm\">\n <Form.Label className=\"d-flex align-content-end align-items-center gap-2 text-primary-500\">\n {showSelectedLocation ? intl.formatMessage(messages.selectedProblem)\n : (\n <>\n {fieldLabel}\n <OverlayTrigger\n placement=\"top\"\n overlay={(\n <Tooltip id=\"problem-location-tooltip\" className=\"info-tooltip\">\n {intl.formatMessage(messages.problemLocationTooltip)}\n </Tooltip>\n )}\n >\n <Icon src={InfoOutline} size=\"sm\" aria-label={intl.formatMessage(messages.problemLocationInfoIconLabel)} />\n </OverlayTrigger>\n </>\n )}\n </Form.Label>\n <div className=\"d-flex align-items-center\">\n {showSelectedLocation && data && !error ? (\n <div className=\"d-flex gap-3 align-items-center col-8 p-0\">\n <div className=\"d-block w-100\">\n <p className=\"x-small mb-0 text-primary-500 text-truncate\">\n {data.breadcrumbs\n .slice(1, -1)\n .map(breadcrumb => breadcrumb.displayName)\n .join(' > ')}\n </p>\n <p className=\"text-primary-500 mb-0\">{data.name}</p>\n <p className=\"x-small text-gray-700 text-truncate mb-0\">{data.id}</p>\n </div>\n <Button iconBefore={SpinnerIcon} onClick={disableShowSelectedLocation}>{intl.formatMessage(messages.change)}</Button>\n </div>\n ) : (\n <>\n <Form.Control\n type=\"text\"\n placeholder={intl.formatMessage(messages.problemLocationPlaceholder)}\n value={inputValue}\n onChange={handleInputChange}\n className=\"flex-grow-1\"\n size=\"md\"\n />\n {problemResponsesError && (\n <Form.Control.Feedback type=\"invalid\">\n {problemResponsesError}\n </Form.Control.Feedback>\n )}\n <Button\n variant=\"primary\"\n onClick={handleClick}\n disabled={disabled || !inputValue}\n className=\"text-nowrap\"\n >\n {buttonLabel}\n </Button>\n </>\n )}\n </div>\n {showSelectedLocation && error\n && isAxiosError(error)\n && (error.response?.status === 400) && (\n <p className=\"text-danger-500 mb-0 x-small mt-2\">\n {intl.formatMessage(messages.problemNotFound, { identifier: inputValue })}\n </p>\n )}\n </Form.Group>\n );\n});\n\nSpecifyProblemField.displayName = 'SpecifyProblemField';\n\nexport default SpecifyProblemField;\n"]}
1
+ {"version":3,"file":"SpecifyProblemField.js","sourceRoot":"","sources":["../../src/components/SpecifyProblemField.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState, useImperativeHandle, forwardRef } from 'react';\nimport { isAxiosError } from 'axios';\nimport { useParams } from 'react-router-dom';\nimport { Button, Form, Icon, OverlayTrigger, Tooltip, useToggle } from '@openedx/paragon';\nimport { InfoOutline, SpinnerIcon } from '@openedx/paragon/icons';\nimport { useIntl } from '@openedx/frontend-base';\nimport messages from './messages';\nimport { useDebouncedFilter } from '@src/hooks/useDebouncedFilter';\nimport { useProblemDetails } from '@src/data/apiHook';\n\ninterface SpecifyProblemFieldProps {\n buttonLabel: string,\n disabled?: boolean,\n fieldLabel: string,\n problemResponsesError?: string,\n usernameOrEmail?: string,\n onClickSelect: (problemLocation: string, event: React.MouseEvent<HTMLButtonElement>) => void,\n}\n\ninterface SpecifyProblemFieldRef {\n reset: () => void,\n}\n\nconst SpecifyProblemField = forwardRef<SpecifyProblemFieldRef, SpecifyProblemFieldProps>(({\n buttonLabel,\n disabled,\n fieldLabel,\n problemResponsesError,\n usernameOrEmail = '',\n onClickSelect,\n}, ref) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [problemLocation, setProblemLocation] = useState('');\n const [showSelectedLocation, enableShowSelectedLocation, disableShowSelectedLocation] = useToggle(false);\n\n const { inputValue, handleChange, resetFilter } = useDebouncedFilter({\n filterValue: problemLocation,\n setFilter: setProblemLocation,\n });\n const { data = { breadcrumbs: [], name: '', id: '' }, refetch, error } = useProblemDetails(courseId, inputValue, usernameOrEmail);\n\n useImperativeHandle(ref, () => ({\n reset: () => {\n resetFilter();\n disableShowSelectedLocation();\n }\n }));\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n handleChange(e.target.value);\n\n if (showSelectedLocation) {\n disableShowSelectedLocation();\n }\n };\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (inputValue) {\n refetch().then(() => {\n onClickSelect(inputValue, event);\n enableShowSelectedLocation();\n });\n }\n };\n\n return (\n <Form.Group className=\"mb-0\" isInvalid={!!problemResponsesError} size=\"sm\">\n <Form.Label className=\"d-flex align-content-end align-items-center gap-2 text-primary-500\">\n {showSelectedLocation ? intl.formatMessage(messages.selectedProblem)\n : (\n <>\n {fieldLabel}\n <OverlayTrigger\n placement=\"top\"\n overlay={(\n <Tooltip id=\"problem-location-tooltip\" className=\"info-tooltip\">\n {intl.formatMessage(messages.problemLocationTooltip)}\n </Tooltip>\n )}\n >\n <Icon src={InfoOutline} size=\"sm\" aria-label={intl.formatMessage(messages.problemLocationInfoIconLabel)} />\n </OverlayTrigger>\n </>\n )}\n </Form.Label>\n <div className=\"d-flex align-items-center\">\n {showSelectedLocation && data && !error ? (\n <div className=\"d-flex gap-3 align-items-center col-8 p-0\">\n <div className=\"d-block w-100\">\n <p className=\"x-small mb-0 text-primary-500 text-truncate\">\n {data.breadcrumbs\n .slice(1, -1)\n .map(breadcrumb => breadcrumb.displayName)\n .join(' > ')}\n </p>\n <p className=\"text-primary-500 mb-0\">{data.name}</p>\n <p className=\"x-small text-gray-700 text-truncate mb-0\">{data.id}</p>\n </div>\n <Button iconBefore={SpinnerIcon} onClick={disableShowSelectedLocation}>{intl.formatMessage(messages.change)}</Button>\n </div>\n ) : (\n <>\n <Form.Control\n type=\"text\"\n placeholder={intl.formatMessage(messages.problemLocationPlaceholder)}\n value={inputValue}\n onChange={handleInputChange}\n className=\"flex-grow-1\"\n size=\"md\"\n />\n {problemResponsesError && (\n <Form.Control.Feedback type=\"invalid\">\n {problemResponsesError}\n </Form.Control.Feedback>\n )}\n <Button\n variant=\"primary\"\n onClick={handleClick}\n disabled={disabled || !inputValue}\n className=\"text-nowrap\"\n >\n {buttonLabel}\n </Button>\n </>\n )}\n </div>\n {showSelectedLocation && error\n && isAxiosError(error)\n && ((error.response?.status === 400) || (error.response?.status === 404)) && (\n <p className=\"text-danger-500 mb-0 x-small mt-2\">\n {intl.formatMessage(messages.problemNotFound, { identifier: inputValue })}\n </p>\n )}\n </Form.Group>\n );\n});\n\nSpecifyProblemField.displayName = 'SpecifyProblemField';\n\nexport default SpecifyProblemField;\n"]}
@@ -154,5 +154,10 @@ declare const messages: {
154
154
  defaultMessage: string;
155
155
  description: string;
156
156
  };
157
+ learnerGenericError: {
158
+ id: string;
159
+ defaultMessage: string;
160
+ description: string;
161
+ };
157
162
  };
158
163
  export default messages;
@@ -155,6 +155,11 @@ const messages = defineMessages({
155
155
  defaultMessage: 'Selected Learner:',
156
156
  description: 'Label for specify learner field when a learner has been selected',
157
157
  },
158
+ learnerGenericError: {
159
+ id: 'instruct.specifyLearner.learnerGenericError',
160
+ defaultMessage: 'An error occurred while looking up {identifier}. Please try again.',
161
+ description: 'Generic error message displayed when there is an error looking up a learner based on the provided identifier (email or username)',
162
+ }
158
163
  });
159
164
  export default messages;
160
165
  //# sourceMappingURL=messages.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/components/messages.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineMessages } from '@openedx/frontend-base';\n\nconst messages = defineMessages({\n select: {\n id: 'instruct.specifyLearner.select',\n defaultMessage: 'Select',\n description: 'Label for select dropdown in specify learner field',\n },\n specifyLearner: {\n id: 'instruct.specifyLearner.label',\n defaultMessage: 'Specify Learner:',\n description: 'Label for specify learner field',\n },\n specifyLearnerPlaceholder: {\n id: 'instruct.specifyLearner.placeholder',\n defaultMessage: 'Learner email address or username',\n description: 'Placeholder text for specify learner input field',\n },\n pageNotFoundHeader: {\n id: 'instruct.pageNotFound.header',\n defaultMessage: 'Page not found',\n description: 'Header for page not found error',\n },\n pageNotFoundBody: {\n id: 'instruct.pageNotFound.body',\n defaultMessage: \"The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again.\",\n description: 'Body text for page not found error',\n },\n pendingTasksTitle: {\n id: 'instruct.pendingTasks.section.title',\n defaultMessage: 'Pending Tasks',\n description: 'Title for the pending tasks section',\n },\n noTasksMessage: {\n id: 'instruct.pendingTasks.section.noTasks',\n defaultMessage: 'No tasks currently running.',\n description: 'Message displayed when there are no pending tasks',\n },\n taskTypeColumnName: {\n id: 'instruct.pendingTasks.table.column.taskType',\n defaultMessage: 'Task Type',\n description: 'Column name for task type in pending tasks table',\n },\n taskInputColumnName: {\n id: 'instruct.pendingTasks.table.column.taskInput',\n defaultMessage: 'Task Input',\n description: 'Column name for task input in pending tasks table',\n },\n taskIdColumnName: {\n id: 'instruct.pendingTasks.table.column.taskId',\n defaultMessage: 'Task ID',\n description: 'Column name for task ID in pending tasks table',\n },\n requesterColumnName: {\n id: 'instruct.pendingTasks.table.column.requester',\n defaultMessage: 'Requester',\n description: 'Column name for requester in pending tasks table',\n },\n taskStateColumnName: {\n id: 'instruct.pendingTasks.table.column.taskState',\n defaultMessage: 'Task State',\n description: 'Column name for task state in pending tasks table',\n },\n createdColumnName: {\n id: 'instruct.pendingTasks.table.column.created',\n defaultMessage: 'Created',\n description: 'Column name for created date in pending tasks table',\n },\n taskOutputColumnName: {\n id: 'instruct.pendingTasks.table.column.taskOutput',\n defaultMessage: 'Task Output',\n description: 'Column name for task output in pending tasks table',\n },\n durationColumnName: {\n id: 'instruct.pendingTasks.table.column.duration',\n defaultMessage: 'Duration (sec)',\n description: 'Column name for duration in pending tasks table',\n },\n statusColumnName: {\n id: 'instruct.pendingTasks.table.column.status',\n defaultMessage: 'Status',\n description: 'Column name for status in pending tasks table',\n },\n taskMessageColumnName: {\n id: 'instruct.pendingTasks.table.column.taskMessage',\n defaultMessage: 'Task Message',\n description: 'Column name for task message in pending tasks table',\n },\n downloadCSVTitle: {\n id: 'instruct.csvComponent.downloadCSVTitle',\n defaultMessage: 'Upload CSV File',\n description: 'Title for the upload CSV file section'\n },\n downloadCSVDescription: {\n id: 'instruct.csvComponent.downloadCSVDescription',\n defaultMessage: 'Only properly formatted CSV files will be accepted',\n description: 'Description for the upload CSV file section'\n },\n viewCSVTemplate: {\n id: 'instruct.csvComponent.viewCSVTemplate',\n defaultMessage: 'View Template',\n description: 'Label for the view CSV template link'\n },\n uploadingFileMessage: {\n id: 'instruct.csvComponent.uploadingFileMessage',\n defaultMessage: 'File chosen: {fileName}',\n description: 'Message displayed when a file is being uploaded, with the file name included'\n },\n change: {\n id: 'instruct.specifyLearner.change',\n defaultMessage: 'Change',\n description: 'Label for change button in specify learner field',\n },\n learnerNotFound: {\n id: 'instruct.specifyLearner.learnerNotFound',\n defaultMessage: 'Could not find student matching identifier: {identifier}',\n description: 'Error message displayed when a learner cannot be found based on the provided identifier (email or username)',\n },\n problemNotFound: {\n id: 'instruct.specifyProblemField.problemNotFound',\n defaultMessage: 'Could not find problem matching identifier: {identifier}',\n description: 'Error message displayed when a problem cannot be found based on the provided identifier',\n },\n searchPlaceholder: {\n id: 'instruct.usernameFilter.searchPlaceholder',\n defaultMessage: 'Search By Username or Email',\n description: 'Placeholder text for the username filter input',\n },\n problemLocationPlaceholder: {\n id: 'instruct.specifyProblemField.locationPlaceholder',\n defaultMessage: 'Problem location',\n description: 'Placeholder text for problem location input',\n },\n problemLocationInfoIconLabel: {\n id: 'instruct.specifyProblemField.infoIconLabel',\n defaultMessage: 'Example format for problem location',\n description: 'Aria label for the info icon next to the problem location input',\n },\n problemLocationTooltip: {\n id: 'instruct.specifyProblemField.locationTooltip',\n defaultMessage: 'Example: block-v1:edX+DemoX+2015+type@problem+block@618c5933b8b544e4a4cc103d3e508378',\n description: 'Tooltip text showing an example problem location format',\n },\n selectedProblem: {\n id: 'instruct.specifyProblemField.selectedProblem',\n defaultMessage: 'Selected Problem:',\n description: 'Label for specify problem field when a problem has been selected',\n },\n learnerNotEnrolled: {\n id: 'instruct.specifyLearner.learnerNotEnrolled',\n defaultMessage: '{identifier} is not enrolled in this course',\n description: 'Error message displayed when a learner is found based on the provided identifier (email or username) but is not enrolled in the course',\n },\n selectedLearner: {\n id: 'instruct.specifyLearner.selectedLearner',\n defaultMessage: 'Selected Learner:',\n description: 'Label for specify learner field when a learner has been selected',\n },\n});\n\nexport default messages;\n"]}
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/components/messages.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineMessages } from '@openedx/frontend-base';\n\nconst messages = defineMessages({\n select: {\n id: 'instruct.specifyLearner.select',\n defaultMessage: 'Select',\n description: 'Label for select dropdown in specify learner field',\n },\n specifyLearner: {\n id: 'instruct.specifyLearner.label',\n defaultMessage: 'Specify Learner:',\n description: 'Label for specify learner field',\n },\n specifyLearnerPlaceholder: {\n id: 'instruct.specifyLearner.placeholder',\n defaultMessage: 'Learner email address or username',\n description: 'Placeholder text for specify learner input field',\n },\n pageNotFoundHeader: {\n id: 'instruct.pageNotFound.header',\n defaultMessage: 'Page not found',\n description: 'Header for page not found error',\n },\n pageNotFoundBody: {\n id: 'instruct.pageNotFound.body',\n defaultMessage: \"The page you're looking for is unavailable or there's an error in the URL. Please check the URL and try again.\",\n description: 'Body text for page not found error',\n },\n pendingTasksTitle: {\n id: 'instruct.pendingTasks.section.title',\n defaultMessage: 'Pending Tasks',\n description: 'Title for the pending tasks section',\n },\n noTasksMessage: {\n id: 'instruct.pendingTasks.section.noTasks',\n defaultMessage: 'No tasks currently running.',\n description: 'Message displayed when there are no pending tasks',\n },\n taskTypeColumnName: {\n id: 'instruct.pendingTasks.table.column.taskType',\n defaultMessage: 'Task Type',\n description: 'Column name for task type in pending tasks table',\n },\n taskInputColumnName: {\n id: 'instruct.pendingTasks.table.column.taskInput',\n defaultMessage: 'Task Input',\n description: 'Column name for task input in pending tasks table',\n },\n taskIdColumnName: {\n id: 'instruct.pendingTasks.table.column.taskId',\n defaultMessage: 'Task ID',\n description: 'Column name for task ID in pending tasks table',\n },\n requesterColumnName: {\n id: 'instruct.pendingTasks.table.column.requester',\n defaultMessage: 'Requester',\n description: 'Column name for requester in pending tasks table',\n },\n taskStateColumnName: {\n id: 'instruct.pendingTasks.table.column.taskState',\n defaultMessage: 'Task State',\n description: 'Column name for task state in pending tasks table',\n },\n createdColumnName: {\n id: 'instruct.pendingTasks.table.column.created',\n defaultMessage: 'Created',\n description: 'Column name for created date in pending tasks table',\n },\n taskOutputColumnName: {\n id: 'instruct.pendingTasks.table.column.taskOutput',\n defaultMessage: 'Task Output',\n description: 'Column name for task output in pending tasks table',\n },\n durationColumnName: {\n id: 'instruct.pendingTasks.table.column.duration',\n defaultMessage: 'Duration (sec)',\n description: 'Column name for duration in pending tasks table',\n },\n statusColumnName: {\n id: 'instruct.pendingTasks.table.column.status',\n defaultMessage: 'Status',\n description: 'Column name for status in pending tasks table',\n },\n taskMessageColumnName: {\n id: 'instruct.pendingTasks.table.column.taskMessage',\n defaultMessage: 'Task Message',\n description: 'Column name for task message in pending tasks table',\n },\n downloadCSVTitle: {\n id: 'instruct.csvComponent.downloadCSVTitle',\n defaultMessage: 'Upload CSV File',\n description: 'Title for the upload CSV file section'\n },\n downloadCSVDescription: {\n id: 'instruct.csvComponent.downloadCSVDescription',\n defaultMessage: 'Only properly formatted CSV files will be accepted',\n description: 'Description for the upload CSV file section'\n },\n viewCSVTemplate: {\n id: 'instruct.csvComponent.viewCSVTemplate',\n defaultMessage: 'View Template',\n description: 'Label for the view CSV template link'\n },\n uploadingFileMessage: {\n id: 'instruct.csvComponent.uploadingFileMessage',\n defaultMessage: 'File chosen: {fileName}',\n description: 'Message displayed when a file is being uploaded, with the file name included'\n },\n change: {\n id: 'instruct.specifyLearner.change',\n defaultMessage: 'Change',\n description: 'Label for change button in specify learner field',\n },\n learnerNotFound: {\n id: 'instruct.specifyLearner.learnerNotFound',\n defaultMessage: 'Could not find student matching identifier: {identifier}',\n description: 'Error message displayed when a learner cannot be found based on the provided identifier (email or username)',\n },\n problemNotFound: {\n id: 'instruct.specifyProblemField.problemNotFound',\n defaultMessage: 'Could not find problem matching identifier: {identifier}',\n description: 'Error message displayed when a problem cannot be found based on the provided identifier',\n },\n searchPlaceholder: {\n id: 'instruct.usernameFilter.searchPlaceholder',\n defaultMessage: 'Search By Username or Email',\n description: 'Placeholder text for the username filter input',\n },\n problemLocationPlaceholder: {\n id: 'instruct.specifyProblemField.locationPlaceholder',\n defaultMessage: 'Problem location',\n description: 'Placeholder text for problem location input',\n },\n problemLocationInfoIconLabel: {\n id: 'instruct.specifyProblemField.infoIconLabel',\n defaultMessage: 'Example format for problem location',\n description: 'Aria label for the info icon next to the problem location input',\n },\n problemLocationTooltip: {\n id: 'instruct.specifyProblemField.locationTooltip',\n defaultMessage: 'Example: block-v1:edX+DemoX+2015+type@problem+block@618c5933b8b544e4a4cc103d3e508378',\n description: 'Tooltip text showing an example problem location format',\n },\n selectedProblem: {\n id: 'instruct.specifyProblemField.selectedProblem',\n defaultMessage: 'Selected Problem:',\n description: 'Label for specify problem field when a problem has been selected',\n },\n learnerNotEnrolled: {\n id: 'instruct.specifyLearner.learnerNotEnrolled',\n defaultMessage: '{identifier} is not enrolled in this course',\n description: 'Error message displayed when a learner is found based on the provided identifier (email or username) but is not enrolled in the course',\n },\n selectedLearner: {\n id: 'instruct.specifyLearner.selectedLearner',\n defaultMessage: 'Selected Learner:',\n description: 'Label for specify learner field when a learner has been selected',\n },\n learnerGenericError: {\n id: 'instruct.specifyLearner.learnerGenericError',\n defaultMessage: 'An error occurred while looking up {identifier}. Please try again.',\n description: 'Generic error message displayed when there is an error looking up a learner based on the provided identifier (email or username)',\n }\n});\n\nexport default messages;\n"]}
@@ -17,8 +17,9 @@ const UpdateBetaTesterModal = ({ learner, isOpen, onClose }) => {
17
17
  action: learner.isBetaTester ? 'remove' : 'add',
18
18
  }, {
19
19
  onSuccess: (data) => {
20
- var _a;
20
+ var _a, _b;
21
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)) || [];
22
23
  if (failedUsernames.length > 0) {
23
24
  addAlert({
24
25
  type: 'danger',
@@ -26,6 +27,13 @@ const UpdateBetaTesterModal = ({ learner, isOpen, onClose }) => {
26
27
  extraContent: (failedUsernames.map((learner) => (_jsxs("p", { className: "mb-0", children: ["\u2022 ", intl.formatMessage(messages.unknownLearner, { learner })] }, learner))))
27
28
  });
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
+ }
29
37
  },
30
38
  onError: () => {
31
39
  showModal({
@@ -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 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 },\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 } 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"]}
@@ -104,7 +104,11 @@ const GradingLearnerContent = ({ toolType, onShowTasks }) => {
104
104
  setBlockId(location);
105
105
  };
106
106
  const handleLearnerChange = (usernameOrEmail) => {
107
+ var _a;
107
108
  setUsernameOrEmail(usernameOrEmail);
109
+ // Reset problem field when learner changes due to progress and attempts change for every learner
110
+ setBlockId('');
111
+ (_a = problemFieldRef.current) === null || _a === void 0 ? void 0 : _a.reset();
108
112
  };
109
113
  return (_jsxs(_Fragment, { children: [_jsx("p", { className: "x-small text-primary mt-3", children: toolType === 'single'
110
114
  ? intl.formatMessage(messages.descriptionSingleLearner)
@@ -1 +1 @@
1
- {"version":3,"file":"GradingLearnerContent.js","sourceRoot":"","sources":["../../../src/grading/components/GradingLearnerContent.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useParams } from 'react-router-dom';\nimport { useEffect, useState, useRef } from 'react';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Button, FormControl } from '@openedx/paragon';\nimport ActionCard, { ActionCardProps } from '@src/components/ActionCard';\nimport SpecifyLearnerField from '@src/components/SpecifyLearnerField';\nimport SpecifyProblemField from '@src/components/SpecifyProblemField';\nimport { useChangeScore, useDeleteHistory, useRescoreSubmission, useResetAttempts } from '@src/grading/data/apiHook';\nimport messages from '@src/grading/messages';\nimport { GradingToolsType } from '@src/grading/types';\nimport { usePendingTasks } from '@src/data/apiHook';\n\ninterface GradingLearnerContentProps {\n toolType: GradingToolsType,\n onShowTasks: () => void,\n}\n\nconst GradingLearnerContent = ({ toolType, onShowTasks }: GradingLearnerContentProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [usernameOrEmail, setUsernameOrEmail] = useState('');\n const [blockId, setBlockId] = useState('');\n const [score, setScore] = useState('');\n const learnerFieldRef = useRef<{ reset: () => void }>(null);\n const problemFieldRef = useRef<{ reset: () => void }>(null);\n\n const { mutate: resetAttempts } = useResetAttempts(courseId);\n const { mutate: deleteHistory } = useDeleteHistory(courseId);\n const { mutate: changeScore } = useChangeScore(courseId);\n const { mutate: rescoreSubmission } = useRescoreSubmission(courseId);\n const { refetch: refetchTasks } = usePendingTasks(courseId);\n\n const handleResetAttempts = (): void => {\n resetAttempts({ learner: usernameOrEmail, problem: blockId });\n };\n\n const handleRescoreSubmission = (onlyIfHigher = false): void => {\n rescoreSubmission({ learner: usernameOrEmail, problem: blockId, onlyIfHigher });\n };\n\n const handleDeleteHistory = (): void => {\n deleteHistory({ learner: usernameOrEmail, problem: blockId });\n };\n\n const handleOverrideScore = (): void => {\n changeScore({ learner: usernameOrEmail, problem: blockId, newScore: Number(score) });\n };\n\n const handleScoreChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const value = e.target.value;\n const numericRegex = /^-?\\d*\\.?\\d*$/;\n\n if (numericRegex.test(value) || value === '') {\n setScore(value);\n }\n };\n\n const handleTaskStatusClick = (): void => {\n refetchTasks();\n onShowTasks();\n };\n\n useEffect(() => {\n setUsernameOrEmail('');\n setBlockId('');\n setScore('');\n learnerFieldRef.current?.reset();\n problemFieldRef.current?.reset();\n }, [toolType]);\n\n const singleLearnerActionRows: ActionCardProps[] = [\n {\n title: intl.formatMessage(messages.resetAttempts),\n description: intl.formatMessage(messages.resetAttemptsDescription),\n customAction: (\n <Button disabled={!usernameOrEmail || !blockId} onClick={handleResetAttempts}>\n {intl.formatMessage(messages.resetAttemptsButtonLabel)}\n </Button>\n )\n },\n {\n title: intl.formatMessage(messages.rescoreSubmission),\n description: intl.formatMessage(messages.rescoreSubmissionDescription),\n customAction: (\n <div className=\"d-flex flex-column gap-3\">\n <Button disabled={!usernameOrEmail || !blockId} onClick={() => handleRescoreSubmission()}>{intl.formatMessage(messages.rescoreSubmissionButtonLabel)}</Button>\n <Button disabled={!usernameOrEmail || !blockId} onClick={() => handleRescoreSubmission(true)}>{intl.formatMessage(messages.rescoreIfImprovesScoreButtonLabel)}</Button>\n </div>\n ),\n },\n {\n title: intl.formatMessage(messages.overrideScore),\n description: intl.formatMessage(messages.overrideScoreDescription),\n buttonLabel: intl.formatMessage(messages.overrideScoreButtonLabel),\n customAction: (\n <div className=\"d-flex align-items-center gap-2\">\n <FormControl\n name={intl.formatMessage(messages.overrideScorePlaceholder)}\n type=\"number\"\n placeholder={intl.formatMessage(messages.overrideScorePlaceholder)}\n value={score}\n onChange={handleScoreChange}\n />\n <Button disabled={!usernameOrEmail || !blockId || !score} onClick={handleOverrideScore}>{intl.formatMessage(messages.overrideScoreButtonLabel)}</Button>\n </div>\n )\n },\n {\n title: intl.formatMessage(messages.deleteHistory),\n description: intl.formatMessage(messages.deleteHistoryDescription),\n customAction: (\n <div className=\"d-flex flex-column gap-3\">\n <Button disabled={!usernameOrEmail || !blockId} onClick={handleDeleteHistory}>{intl.formatMessage(messages.deleteHistoryButtonLabel)}</Button>\n </div>\n ),\n },\n {\n title: intl.formatMessage(messages.taskStatus),\n description: intl.formatMessage(messages.taskStatusDescription),\n customAction: (\n <Button disabled={!usernameOrEmail || !blockId} onClick={handleTaskStatusClick}>\n {intl.formatMessage(messages.taskStatusButtonLabel)}\n </Button>\n )\n }\n ];\n\n const allLearnersActionRows = [\n {\n title: intl.formatMessage(messages.resetAttempts),\n description: intl.formatMessage(messages.resetAllLearnersAttemptsDescription),\n buttonLabel: intl.formatMessage(messages.resetAttemptsButtonLabel),\n customAction: (\n <Button disabled={!blockId} onClick={handleResetAttempts}>\n {intl.formatMessage(messages.resetAttemptsButtonLabel)}\n </Button>\n )\n },\n {\n title: intl.formatMessage(messages.rescoreSubmission),\n description: intl.formatMessage(messages.rescoreSubmissionAllLearnersDescription),\n customAction: (\n <div className=\"d-flex flex-column gap-3\">\n <Button disabled={!blockId} onClick={() => handleRescoreSubmission()}>{intl.formatMessage(messages.rescoreAllSubmissionButtonLabel)}</Button>\n <Button disabled={!blockId} onClick={() => handleRescoreSubmission(true)}>{intl.formatMessage(messages.rescoreIfImprovesScoreButtonLabel)}</Button>\n </div>\n ),\n },\n {\n title: intl.formatMessage(messages.taskStatus),\n description: intl.formatMessage(messages.taskStatusDescription),\n customAction: (\n <Button onClick={handleTaskStatusClick}>\n {intl.formatMessage(messages.taskStatusButtonLabel)}\n </Button>\n )\n }\n ];\n\n const rows = toolType === 'single' ? singleLearnerActionRows : allLearnersActionRows;\n\n const handleProblemChange = (location: string): void => {\n setBlockId(location);\n };\n\n const handleLearnerChange = (usernameOrEmail: string): void => {\n setUsernameOrEmail(usernameOrEmail);\n };\n\n return (\n <>\n <p className=\"x-small text-primary mt-3\">\n {\n toolType === 'single'\n ? intl.formatMessage(messages.descriptionSingleLearner)\n : intl.formatMessage(messages.descriptionAllLearners)\n }\n </p>\n <div className=\"d-flex justify-content-between gap-4\">\n {toolType === 'single' && (\n <div className=\"w-50\">\n <SpecifyLearnerField ref={learnerFieldRef} onClickSelect={handleLearnerChange} />\n </div>\n )}\n <div className=\"w-50\">\n <SpecifyProblemField\n ref={problemFieldRef}\n fieldLabel={intl.formatMessage(messages.specifyProblem)}\n buttonLabel={intl.formatMessage(messages.select)}\n disabled={!usernameOrEmail && toolType === 'single'}\n usernameOrEmail={usernameOrEmail}\n onClickSelect={handleProblemChange}\n />\n </div>\n </div>\n {\n rows.map(({ title, description, buttonLabel, customAction, onButtonClick }, index) => (\n <ActionCard key={title} buttonLabel={buttonLabel} description={description} title={title} hasBorderBottom={index !== rows.length - 1} customAction={customAction} onButtonClick={onButtonClick} />\n ))\n }\n </>\n );\n};\n\nexport default GradingLearnerContent;\n"]}
1
+ {"version":3,"file":"GradingLearnerContent.js","sourceRoot":"","sources":["../../../src/grading/components/GradingLearnerContent.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useParams } from 'react-router-dom';\nimport { useEffect, useState, useRef } from 'react';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Button, FormControl } from '@openedx/paragon';\nimport ActionCard, { ActionCardProps } from '@src/components/ActionCard';\nimport SpecifyLearnerField from '@src/components/SpecifyLearnerField';\nimport SpecifyProblemField from '@src/components/SpecifyProblemField';\nimport { useChangeScore, useDeleteHistory, useRescoreSubmission, useResetAttempts } from '@src/grading/data/apiHook';\nimport messages from '@src/grading/messages';\nimport { GradingToolsType } from '@src/grading/types';\nimport { usePendingTasks } from '@src/data/apiHook';\n\ninterface GradingLearnerContentProps {\n toolType: GradingToolsType,\n onShowTasks: () => void,\n}\n\nconst GradingLearnerContent = ({ toolType, onShowTasks }: GradingLearnerContentProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [usernameOrEmail, setUsernameOrEmail] = useState('');\n const [blockId, setBlockId] = useState('');\n const [score, setScore] = useState('');\n const learnerFieldRef = useRef<{ reset: () => void }>(null);\n const problemFieldRef = useRef<{ reset: () => void }>(null);\n\n const { mutate: resetAttempts } = useResetAttempts(courseId);\n const { mutate: deleteHistory } = useDeleteHistory(courseId);\n const { mutate: changeScore } = useChangeScore(courseId);\n const { mutate: rescoreSubmission } = useRescoreSubmission(courseId);\n const { refetch: refetchTasks } = usePendingTasks(courseId);\n\n const handleResetAttempts = (): void => {\n resetAttempts({ learner: usernameOrEmail, problem: blockId });\n };\n\n const handleRescoreSubmission = (onlyIfHigher = false): void => {\n rescoreSubmission({ learner: usernameOrEmail, problem: blockId, onlyIfHigher });\n };\n\n const handleDeleteHistory = (): void => {\n deleteHistory({ learner: usernameOrEmail, problem: blockId });\n };\n\n const handleOverrideScore = (): void => {\n changeScore({ learner: usernameOrEmail, problem: blockId, newScore: Number(score) });\n };\n\n const handleScoreChange = (e: React.ChangeEvent<HTMLInputElement>): void => {\n const value = e.target.value;\n const numericRegex = /^-?\\d*\\.?\\d*$/;\n\n if (numericRegex.test(value) || value === '') {\n setScore(value);\n }\n };\n\n const handleTaskStatusClick = (): void => {\n refetchTasks();\n onShowTasks();\n };\n\n useEffect(() => {\n setUsernameOrEmail('');\n setBlockId('');\n setScore('');\n learnerFieldRef.current?.reset();\n problemFieldRef.current?.reset();\n }, [toolType]);\n\n const singleLearnerActionRows: ActionCardProps[] = [\n {\n title: intl.formatMessage(messages.resetAttempts),\n description: intl.formatMessage(messages.resetAttemptsDescription),\n customAction: (\n <Button disabled={!usernameOrEmail || !blockId} onClick={handleResetAttempts}>\n {intl.formatMessage(messages.resetAttemptsButtonLabel)}\n </Button>\n )\n },\n {\n title: intl.formatMessage(messages.rescoreSubmission),\n description: intl.formatMessage(messages.rescoreSubmissionDescription),\n customAction: (\n <div className=\"d-flex flex-column gap-3\">\n <Button disabled={!usernameOrEmail || !blockId} onClick={() => handleRescoreSubmission()}>{intl.formatMessage(messages.rescoreSubmissionButtonLabel)}</Button>\n <Button disabled={!usernameOrEmail || !blockId} onClick={() => handleRescoreSubmission(true)}>{intl.formatMessage(messages.rescoreIfImprovesScoreButtonLabel)}</Button>\n </div>\n ),\n },\n {\n title: intl.formatMessage(messages.overrideScore),\n description: intl.formatMessage(messages.overrideScoreDescription),\n buttonLabel: intl.formatMessage(messages.overrideScoreButtonLabel),\n customAction: (\n <div className=\"d-flex align-items-center gap-2\">\n <FormControl\n name={intl.formatMessage(messages.overrideScorePlaceholder)}\n type=\"number\"\n placeholder={intl.formatMessage(messages.overrideScorePlaceholder)}\n value={score}\n onChange={handleScoreChange}\n />\n <Button disabled={!usernameOrEmail || !blockId || !score} onClick={handleOverrideScore}>{intl.formatMessage(messages.overrideScoreButtonLabel)}</Button>\n </div>\n )\n },\n {\n title: intl.formatMessage(messages.deleteHistory),\n description: intl.formatMessage(messages.deleteHistoryDescription),\n customAction: (\n <div className=\"d-flex flex-column gap-3\">\n <Button disabled={!usernameOrEmail || !blockId} onClick={handleDeleteHistory}>{intl.formatMessage(messages.deleteHistoryButtonLabel)}</Button>\n </div>\n ),\n },\n {\n title: intl.formatMessage(messages.taskStatus),\n description: intl.formatMessage(messages.taskStatusDescription),\n customAction: (\n <Button disabled={!usernameOrEmail || !blockId} onClick={handleTaskStatusClick}>\n {intl.formatMessage(messages.taskStatusButtonLabel)}\n </Button>\n )\n }\n ];\n\n const allLearnersActionRows = [\n {\n title: intl.formatMessage(messages.resetAttempts),\n description: intl.formatMessage(messages.resetAllLearnersAttemptsDescription),\n buttonLabel: intl.formatMessage(messages.resetAttemptsButtonLabel),\n customAction: (\n <Button disabled={!blockId} onClick={handleResetAttempts}>\n {intl.formatMessage(messages.resetAttemptsButtonLabel)}\n </Button>\n )\n },\n {\n title: intl.formatMessage(messages.rescoreSubmission),\n description: intl.formatMessage(messages.rescoreSubmissionAllLearnersDescription),\n customAction: (\n <div className=\"d-flex flex-column gap-3\">\n <Button disabled={!blockId} onClick={() => handleRescoreSubmission()}>{intl.formatMessage(messages.rescoreAllSubmissionButtonLabel)}</Button>\n <Button disabled={!blockId} onClick={() => handleRescoreSubmission(true)}>{intl.formatMessage(messages.rescoreIfImprovesScoreButtonLabel)}</Button>\n </div>\n ),\n },\n {\n title: intl.formatMessage(messages.taskStatus),\n description: intl.formatMessage(messages.taskStatusDescription),\n customAction: (\n <Button onClick={handleTaskStatusClick}>\n {intl.formatMessage(messages.taskStatusButtonLabel)}\n </Button>\n )\n }\n ];\n\n const rows = toolType === 'single' ? singleLearnerActionRows : allLearnersActionRows;\n\n const handleProblemChange = (location: string): void => {\n setBlockId(location);\n };\n\n const handleLearnerChange = (usernameOrEmail: string): void => {\n setUsernameOrEmail(usernameOrEmail);\n // Reset problem field when learner changes due to progress and attempts change for every learner\n setBlockId('');\n problemFieldRef.current?.reset();\n };\n\n return (\n <>\n <p className=\"x-small text-primary mt-3\">\n {\n toolType === 'single'\n ? intl.formatMessage(messages.descriptionSingleLearner)\n : intl.formatMessage(messages.descriptionAllLearners)\n }\n </p>\n <div className=\"d-flex justify-content-between gap-4\">\n {toolType === 'single' && (\n <div className=\"w-50\">\n <SpecifyLearnerField ref={learnerFieldRef} onClickSelect={handleLearnerChange} />\n </div>\n )}\n <div className=\"w-50\">\n <SpecifyProblemField\n ref={problemFieldRef}\n fieldLabel={intl.formatMessage(messages.specifyProblem)}\n buttonLabel={intl.formatMessage(messages.select)}\n disabled={!usernameOrEmail && toolType === 'single'}\n usernameOrEmail={usernameOrEmail}\n onClickSelect={handleProblemChange}\n />\n </div>\n </div>\n {\n rows.map(({ title, description, buttonLabel, customAction, onButtonClick }, index) => (\n <ActionCard key={title} buttonLabel={buttonLabel} description={description} title={title} hasBorderBottom={index !== rows.length - 1} customAction={customAction} onButtonClick={onButtonClick} />\n ))\n }\n </>\n );\n};\n\nexport default GradingLearnerContent;\n"]}
@@ -0,0 +1,2 @@
1
+ declare const CourseInfoSlot: () => import("react/jsx-runtime").JSX.Element | null;
2
+ export default CourseInfoSlot;
@@ -0,0 +1,14 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useParams } from 'react-router-dom';
3
+ import { useCourseInfo } from '../../data/apiHook';
4
+ const CourseInfoSlot = () => {
5
+ const { courseId = '' } = useParams();
6
+ const { data } = useCourseInfo(courseId);
7
+ if (!data) {
8
+ return null;
9
+ }
10
+ const { org = '', courseNumber = '', displayName = '' } = data;
11
+ return (_jsxs("div", { style: { minWidth: 0, lineHeight: '1' }, children: [_jsxs("span", { className: "d-block small m-0", children: [org, " ", courseNumber] }), _jsx("span", { className: "d-block m-0 font-weight-bold course-title", children: displayName })] }));
12
+ };
13
+ export default CourseInfoSlot;
14
+ //# sourceMappingURL=CourseInfoSlot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CourseInfoSlot.js","sourceRoot":"","sources":["../../../src/slots/CourseInfoSlot/CourseInfoSlot.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,cAAc,GAAG,GAAG,EAAE;IAC1B,MAAM,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,SAAS,EAAE,CAAC;IACtC,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAEzC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,EAAE,GAAG,GAAG,EAAE,EAAE,YAAY,GAAG,EAAE,EAAE,WAAW,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;IAE/D,OAAO,CACL,eAAK,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,aAC1C,gBAAM,SAAS,EAAC,mBAAmB,aAAE,GAAG,OAAG,YAAY,IAAQ,EAC/D,eAAM,SAAS,EAAC,2CAA2C,YAAE,WAAW,GAAQ,IAC5E,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC","sourcesContent":["import { useParams } from 'react-router-dom';\nimport { useCourseInfo } from '@src/data/apiHook';\n\nconst CourseInfoSlot = () => {\n const { courseId = '' } = useParams();\n const { data } = useCourseInfo(courseId);\n\n if (!data) {\n return null;\n }\n\n const { org = '', courseNumber = '', displayName = '' } = data;\n\n return (\n <div style={{ minWidth: 0, lineHeight: '1' }}>\n <span className=\"d-block small m-0\">{org} {courseNumber}</span>\n <span className=\"d-block m-0 font-weight-bold course-title\">{displayName}</span>\n </div>\n );\n};\n\nexport default CourseInfoSlot;\n"]}
package/dist/slots.js CHANGED
@@ -1,7 +1,15 @@
1
- import { helpButtonSlotOperation } from '@openedx/frontend-base';
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { helpButtonSlotOperation, WidgetOperationTypes } from '@openedx/frontend-base';
3
+ import CourseInfoSlot from './slots/CourseInfoSlot/CourseInfoSlot';
2
4
  import { appId, instructorDashboardRole } from './constants';
3
5
  const slots = [
4
6
  helpButtonSlotOperation({ appId, role: instructorDashboardRole }),
7
+ {
8
+ slotId: 'org.openedx.frontend.slot.header.primaryLinks.v1',
9
+ id: 'org.openedx.frontend.widget.slotShowcase.headerLink',
10
+ op: WidgetOperationTypes.APPEND,
11
+ element: _jsx(CourseInfoSlot, {}),
12
+ },
5
13
  ];
6
14
  export default slots;
7
15
  //# sourceMappingURL=slots.js.map
package/dist/slots.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"slots.js","sourceRoot":"","sources":["../src/slots.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAiB,MAAM,wBAAwB,CAAC;AAEhF,OAAO,EAAE,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE7D,MAAM,KAAK,GAAoB;IAC7B,uBAAuB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,uBAAuB,EAAE,CAAC;CAClE,CAAC;AAEF,eAAe,KAAK,CAAC","sourcesContent":["import { helpButtonSlotOperation, SlotOperation } from '@openedx/frontend-base';\n\nimport { appId, instructorDashboardRole } from './constants';\n\nconst slots: SlotOperation[] = [\n helpButtonSlotOperation({ appId, role: instructorDashboardRole }),\n];\n\nexport default slots;\n"]}
1
+ {"version":3,"file":"slots.js","sourceRoot":"","sources":["../src/slots.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,uBAAuB,EAAiB,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACtG,OAAO,cAAc,MAAM,0CAA0C,CAAC;AACtE,OAAO,EAAE,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAEhE,MAAM,KAAK,GAAoB;IAC7B,uBAAuB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,uBAAuB,EAAE,CAAC;IACjE;QACE,MAAM,EAAE,kDAAkD;QAC1D,EAAE,EAAE,qDAAqD;QACzD,EAAE,EAAE,oBAAoB,CAAC,MAAM;QAC/B,OAAO,EAAE,KAAC,cAAc,KAAG;KAC5B;CACF,CAAC;AAEF,eAAe,KAAK,CAAC","sourcesContent":["import { helpButtonSlotOperation, SlotOperation, WidgetOperationTypes } from '@openedx/frontend-base';\nimport CourseInfoSlot from '@src/slots/CourseInfoSlot/CourseInfoSlot';\nimport { appId, instructorDashboardRole } from '@src/constants';\n\nconst slots: SlotOperation[] = [\n helpButtonSlotOperation({ appId, role: instructorDashboardRole }),\n {\n slotId: 'org.openedx.frontend.slot.header.primaryLinks.v1',\n id: 'org.openedx.frontend.widget.slotShowcase.headerLink',\n op: WidgetOperationTypes.APPEND,\n element: <CourseInfoSlot />,\n },\n];\n\nexport default slots;\n"]}
@@ -11,7 +11,7 @@ import messages from '../../specialExams/messages';
11
11
  const AllowancesList = ({ onClickAdd, onEdit, onDelete }) => {
12
12
  const intl = useIntl();
13
13
  const { courseId = '' } = useParams();
14
- const [filters, setFilters] = useState({ page: 0, emailOrUsername: '' });
14
+ const [filters, setFilters] = useState({ page: 0, emailOrUsername: '', ordering: '' });
15
15
  const { data = { results: [], count: 0, numPages: 1 }, isLoading = false } = useAllowances(courseId, Object.assign({ pageSize: ALLOWANCES_PAGE_SIZE }, filters));
16
16
  const ActionCustomCell = ({ row: { original } }) => {
17
17
  const popoverContent = (_jsx(Popover, { id: `popover-${original.user.username}-${original.proctoredExam.examName}`, className: "border-0 shadow-sm", children: _jsx(Popover.Content, { className: "p-0 border-0", children: _jsxs("div", { className: "dropdown-menu show position-static border shadow-sm", children: [_jsx("button", { type: "button", className: "dropdown-item", onClick: () => onEdit(original), children: intl.formatMessage(messages.edit) }), _jsx("button", { type: "button", className: "dropdown-item", onClick: () => onDelete(original), children: intl.formatMessage(messages.delete) })] }) }) }));
@@ -35,11 +35,13 @@ const AllowancesList = ({ onClickAdd, onEdit, onDelete }) => {
35
35
  Cell: ActionCustomCell,
36
36
  }];
37
37
  const handleFetchData = (data) => {
38
- var _a;
38
+ var _a, _b;
39
39
  const emailOrUsernameFilter = (_a = data.filters) === null || _a === void 0 ? void 0 : _a.find((f) => f.id === 'user.username');
40
40
  const newEmailOrUsername = emailOrUsernameFilter ? emailOrUsernameFilter.value : '';
41
- if (filters.emailOrUsername !== newEmailOrUsername) {
42
- setFilters((prevFilters) => (Object.assign(Object.assign({}, prevFilters), { emailOrUsername: newEmailOrUsername, page: 0 })));
41
+ const newOrdering = ((_b = data.sortBy) === null || _b === void 0 ? void 0 : _b[0]) ? `${data.sortBy[0].desc ? '-' : ''}${data.sortBy[0].id}` : '';
42
+ const filtersChanged = newEmailOrUsername !== filters.emailOrUsername || newOrdering !== filters.ordering;
43
+ if (filtersChanged) {
44
+ setFilters((prevFilters) => (Object.assign(Object.assign({}, prevFilters), { emailOrUsername: newEmailOrUsername, ordering: newOrdering, page: 0 })));
43
45
  return;
44
46
  }
45
47
  if (data.pageIndex !== filters.page) {
@@ -51,6 +53,9 @@ const AllowancesList = ({ onClickAdd, onEdit, onDelete }) => {
51
53
  pageSize: ALLOWANCES_PAGE_SIZE,
52
54
  filters: [
53
55
  { id: 'emailOrUsername', value: filters.emailOrUsername }
56
+ ],
57
+ sortBy: [
58
+ { id: filters.ordering.replace(/^-/, ''), desc: filters.ordering.startsWith('-') }
54
59
  ]
55
60
  }, fetchData: handleFetchData, isFilterable: true, isLoading: isLoading, isPaginated: true, isSortable: true, itemCount: data.count, manualFilters: true, manualPagination: true, manualSortBy: true, pageSize: ALLOWANCES_PAGE_SIZE, pageCount: data.numPages, FilterStatusComponent: () => null, children: [_jsxs("div", { className: "bg-light-200 d-flex justify-content-between align-items-center p-3", children: [_jsx(DataTable.TableControlBar, { className: "p-0" }), _jsx(Button, { iconBefore: Plus, variant: "primary", onClick: onClickAdd, children: intl.formatMessage(messages.addAllowance) })] }), _jsx(DataTable.Table, {}), _jsx(DataTable.EmptyTable, { content: intl.formatMessage(messages.noAllowances) }), _jsx(DataTable.TableFooter, {})] }));
56
61
  };
@@ -1 +1 @@
1
- {"version":3,"file":"AllowancesList.js","sourceRoot":"","sources":["../../../src/specialExams/components/AllowancesList.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Button, DataTable, IconButton, OverlayTrigger, Popover } from '@openedx/paragon';\nimport { MoreVert, Plus } from '@openedx/paragon/icons';\nimport UsernameFilter from '@src/components/UsernameFilter';\nimport { ALLOWANCES_PAGE_SIZE, allowanceTypesOptions } from '@src/specialExams/constants';\nimport { useAllowances } from '@src/specialExams/data/apiHook';\nimport messages from '@src/specialExams/messages';\nimport { Allowance } from '@src/specialExams/types';\nimport { DataTableFetchDataProps, TableCellValue } from '@src/types';\n\ninterface AllowanceList {\n onClickAdd: () => void,\n onEdit: (allowance: Allowance) => void,\n onDelete: (allowance: Allowance) => void,\n}\n\nconst AllowancesList = ({ onClickAdd, onEdit, onDelete }: AllowanceList) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [filters, setFilters] = useState({ page: 0, emailOrUsername: '' });\n const { data = { results: [], count: 0, numPages: 1 }, isLoading = false } = useAllowances(courseId, {\n pageSize: ALLOWANCES_PAGE_SIZE,\n ...filters,\n });\n\n const ActionCustomCell = ({ row: { original } }: TableCellValue<Allowance>) => {\n const popoverContent = (\n <Popover\n id={`popover-${original.user.username}-${original.proctoredExam.examName}`}\n className=\"border-0 shadow-sm\"\n >\n <Popover.Content className=\"p-0 border-0\">\n <div className=\"dropdown-menu show position-static border shadow-sm\">\n <button\n type=\"button\"\n className=\"dropdown-item\"\n onClick={() => onEdit(original)}\n >\n {intl.formatMessage(messages.edit)}\n </button>\n <button\n type=\"button\"\n className=\"dropdown-item\"\n onClick={() => onDelete(original)}\n >\n {intl.formatMessage(messages.delete)}\n </button>\n </div>\n </Popover.Content>\n </Popover>\n );\n return (\n <>\n <OverlayTrigger\n trigger=\"click\"\n placement=\"bottom-end\"\n overlay={popoverContent}\n rootClose\n >\n <IconButton\n alt={intl.formatMessage(messages.actions)}\n className=\"lead\"\n iconAs={MoreVert}\n />\n </OverlayTrigger>\n </>\n );\n };\n\n const columns = [\n { accessor: 'user.username', Header: intl.formatMessage(messages.username), Filter: UsernameFilter, },\n { accessor: 'user.email', Header: intl.formatMessage(messages.email), disableFilters: true, },\n { accessor: 'proctoredExam.examName', Header: intl.formatMessage(messages.examName), disableFilters: true, },\n { accessor: 'key', Header: intl.formatMessage(messages.allowanceType), disableFilters: true,\n Cell: ({ value }: { value: string }) => {\n const allowanceType = allowanceTypesOptions.find(option => option.value === value);\n return allowanceType ? intl.formatMessage(allowanceType.label) : '';\n }\n },\n { accessor: 'value', Header: intl.formatMessage(messages.allowanceValue), disableFilters: true, },\n ];\n\n const additionalColumns = [{\n id: 'actions',\n Header: '',\n Cell: ActionCustomCell,\n }];\n\n const handleFetchData = (data: DataTableFetchDataProps) => {\n const emailOrUsernameFilter = data.filters?.find((f) => f.id === 'user.username');\n const newEmailOrUsername = emailOrUsernameFilter ? emailOrUsernameFilter.value : '';\n if (filters.emailOrUsername !== newEmailOrUsername) {\n setFilters((prevFilters) => ({ ...prevFilters, emailOrUsername: newEmailOrUsername, page: 0 }));\n return;\n }\n if (data.pageIndex !== filters.page) {\n setFilters((prevFilters) => ({ ...prevFilters, page: data.pageIndex }));\n }\n };\n\n return (\n <DataTable\n additionalColumns={additionalColumns}\n className=\"mt-3\"\n columns={columns}\n data={data.results}\n state={{\n pageIndex: filters.page,\n pageSize: ALLOWANCES_PAGE_SIZE,\n filters: [\n { id: 'emailOrUsername', value: filters.emailOrUsername }\n ]\n }}\n fetchData={handleFetchData}\n isFilterable\n isLoading={isLoading}\n isPaginated\n isSortable\n itemCount={data.count}\n manualFilters\n manualPagination\n manualSortBy\n pageSize={ALLOWANCES_PAGE_SIZE}\n pageCount={data.numPages}\n FilterStatusComponent={() => null}\n >\n <div className=\"bg-light-200 d-flex justify-content-between align-items-center p-3\">\n <DataTable.TableControlBar className=\"p-0\" />\n <Button iconBefore={Plus} variant=\"primary\" onClick={onClickAdd}>\n {intl.formatMessage(messages.addAllowance)}\n </Button>\n </div>\n <DataTable.Table />\n <DataTable.EmptyTable content={intl.formatMessage(messages.noAllowances)} />\n <DataTable.TableFooter />\n </DataTable>\n );\n};\n\nexport default AllowancesList;\n"]}
1
+ {"version":3,"file":"AllowancesList.js","sourceRoot":"","sources":["../../../src/specialExams/components/AllowancesList.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Button, DataTable, IconButton, OverlayTrigger, Popover } from '@openedx/paragon';\nimport { MoreVert, Plus } from '@openedx/paragon/icons';\nimport UsernameFilter from '@src/components/UsernameFilter';\nimport { ALLOWANCES_PAGE_SIZE, allowanceTypesOptions } from '@src/specialExams/constants';\nimport { useAllowances } from '@src/specialExams/data/apiHook';\nimport messages from '@src/specialExams/messages';\nimport { Allowance } from '@src/specialExams/types';\nimport { DataTableFetchDataProps, TableCellValue } from '@src/types';\n\ninterface AllowanceList {\n onClickAdd: () => void,\n onEdit: (allowance: Allowance) => void,\n onDelete: (allowance: Allowance) => void,\n}\n\nconst AllowancesList = ({ onClickAdd, onEdit, onDelete }: AllowanceList) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [filters, setFilters] = useState({ page: 0, emailOrUsername: '', ordering: '' });\n const { data = { results: [], count: 0, numPages: 1 }, isLoading = false } = useAllowances(courseId, {\n pageSize: ALLOWANCES_PAGE_SIZE,\n ...filters,\n });\n\n const ActionCustomCell = ({ row: { original } }: TableCellValue<Allowance>) => {\n const popoverContent = (\n <Popover\n id={`popover-${original.user.username}-${original.proctoredExam.examName}`}\n className=\"border-0 shadow-sm\"\n >\n <Popover.Content className=\"p-0 border-0\">\n <div className=\"dropdown-menu show position-static border shadow-sm\">\n <button\n type=\"button\"\n className=\"dropdown-item\"\n onClick={() => onEdit(original)}\n >\n {intl.formatMessage(messages.edit)}\n </button>\n <button\n type=\"button\"\n className=\"dropdown-item\"\n onClick={() => onDelete(original)}\n >\n {intl.formatMessage(messages.delete)}\n </button>\n </div>\n </Popover.Content>\n </Popover>\n );\n return (\n <>\n <OverlayTrigger\n trigger=\"click\"\n placement=\"bottom-end\"\n overlay={popoverContent}\n rootClose\n >\n <IconButton\n alt={intl.formatMessage(messages.actions)}\n className=\"lead\"\n iconAs={MoreVert}\n />\n </OverlayTrigger>\n </>\n );\n };\n\n const columns = [\n { accessor: 'user.username', Header: intl.formatMessage(messages.username), Filter: UsernameFilter, },\n { accessor: 'user.email', Header: intl.formatMessage(messages.email), disableFilters: true, },\n { accessor: 'proctoredExam.examName', Header: intl.formatMessage(messages.examName), disableFilters: true, },\n { accessor: 'key', Header: intl.formatMessage(messages.allowanceType), disableFilters: true,\n Cell: ({ value }: { value: string }) => {\n const allowanceType = allowanceTypesOptions.find(option => option.value === value);\n return allowanceType ? intl.formatMessage(allowanceType.label) : '';\n }\n },\n { accessor: 'value', Header: intl.formatMessage(messages.allowanceValue), disableFilters: true, },\n ];\n\n const additionalColumns = [{\n id: 'actions',\n Header: '',\n Cell: ActionCustomCell,\n }];\n\n const handleFetchData = (data: DataTableFetchDataProps) => {\n const emailOrUsernameFilter = data.filters?.find((f) => f.id === 'user.username');\n const newEmailOrUsername = emailOrUsernameFilter ? emailOrUsernameFilter.value : '';\n const newOrdering = data.sortBy?.[0] ? `${data.sortBy[0].desc ? '-' : ''}${data.sortBy[0].id}` : '';\n const filtersChanged = newEmailOrUsername !== filters.emailOrUsername || newOrdering !== filters.ordering;\n if (filtersChanged) {\n setFilters((prevFilters) => ({ ...prevFilters, emailOrUsername: newEmailOrUsername, ordering: newOrdering, page: 0 }));\n return;\n }\n if (data.pageIndex !== filters.page) {\n setFilters((prevFilters) => ({ ...prevFilters, page: data.pageIndex }));\n }\n };\n\n return (\n <DataTable\n additionalColumns={additionalColumns}\n className=\"mt-3\"\n columns={columns}\n data={data.results}\n state={{\n pageIndex: filters.page,\n pageSize: ALLOWANCES_PAGE_SIZE,\n filters: [\n { id: 'emailOrUsername', value: filters.emailOrUsername }\n ],\n sortBy: [\n { id: filters.ordering.replace(/^-/, ''), desc: filters.ordering.startsWith('-') }\n ]\n }}\n fetchData={handleFetchData}\n isFilterable\n isLoading={isLoading}\n isPaginated\n isSortable\n itemCount={data.count}\n manualFilters\n manualPagination\n manualSortBy\n pageSize={ALLOWANCES_PAGE_SIZE}\n pageCount={data.numPages}\n FilterStatusComponent={() => null}\n >\n <div className=\"bg-light-200 d-flex justify-content-between align-items-center p-3\">\n <DataTable.TableControlBar className=\"p-0\" />\n <Button iconBefore={Plus} variant=\"primary\" onClick={onClickAdd}>\n {intl.formatMessage(messages.addAllowance)}\n </Button>\n </div>\n <DataTable.Table />\n <DataTable.EmptyTable content={intl.formatMessage(messages.noAllowances)} />\n <DataTable.TableFooter />\n </DataTable>\n );\n};\n\nexport default AllowancesList;\n"]}
@@ -10,7 +10,7 @@ export const ATTEMPTS_PAGE_SIZE = 25;
10
10
  const AttemptsList = () => {
11
11
  const intl = useIntl();
12
12
  const { courseId = '' } = useParams();
13
- const [filters, setFilters] = useState({ page: 0, emailOrUsername: '' });
13
+ const [filters, setFilters] = useState({ page: 0, emailOrUsername: '', ordering: '' });
14
14
  const { data = { results: [], count: 0, numPages: 0 }, isLoading = false } = useAttempts(courseId, Object.assign(Object.assign({}, filters), { pageSize: ATTEMPTS_PAGE_SIZE }));
15
15
  const columns = useMemo(() => [
16
16
  { accessor: 'user.username', Header: intl.formatMessage(messages.username), Filter: UsernameFilter, },
@@ -22,11 +22,13 @@ const AttemptsList = () => {
22
22
  { accessor: 'status', Header: intl.formatMessage(messages.status), disableFilters: true, },
23
23
  ], [intl]);
24
24
  const handleFetchData = (data) => {
25
- var _a;
25
+ var _a, _b;
26
26
  const emailOrUsernameFilter = (_a = data.filters) === null || _a === void 0 ? void 0 : _a.find((f) => f.id === 'user.username');
27
27
  const newEmailOrUsername = emailOrUsernameFilter ? emailOrUsernameFilter.value : '';
28
- if (filters.emailOrUsername !== newEmailOrUsername) {
29
- setFilters((prevFilters) => (Object.assign(Object.assign({}, prevFilters), { emailOrUsername: newEmailOrUsername, page: 0 })));
28
+ const newOrdering = ((_b = data.sortBy) === null || _b === void 0 ? void 0 : _b[0]) ? `${data.sortBy[0].desc ? '-' : ''}${data.sortBy[0].id}` : '';
29
+ const filtersChanged = newEmailOrUsername !== filters.emailOrUsername || newOrdering !== filters.ordering;
30
+ if (filtersChanged) {
31
+ setFilters((prevFilters) => (Object.assign(Object.assign({}, prevFilters), { emailOrUsername: newEmailOrUsername, ordering: newOrdering, page: 0 })));
30
32
  return;
31
33
  }
32
34
  if (data.pageIndex !== filters.page) {
@@ -38,6 +40,9 @@ const AttemptsList = () => {
38
40
  pageSize: ATTEMPTS_PAGE_SIZE,
39
41
  filters: [
40
42
  { id: 'emailOrUsername', value: filters.emailOrUsername }
43
+ ],
44
+ sortBy: [
45
+ { id: filters.ordering.replace(/^-/, ''), desc: filters.ordering.startsWith('-') }
41
46
  ]
42
47
  }, fetchData: handleFetchData, isFilterable: true, isLoading: isLoading, isPaginated: true, isSortable: true, itemCount: data.count, manualFilters: true, manualPagination: true, manualSortBy: true, pageSize: ATTEMPTS_PAGE_SIZE, pageCount: data.numPages, FilterStatusComponent: () => null, children: [_jsx(DataTable.TableControlBar, { className: "bg-light-200 py-3 px-4" }), _jsx(DataTable.Table, {}), _jsx(DataTable.EmptyTable, { content: intl.formatMessage(messages.noAttempts) }), _jsx(DataTable.TableFooter, {})] }));
43
48
  };
@@ -1 +1 @@
1
- {"version":3,"file":"AttemptsList.js","sourceRoot":"","sources":["../../../src/specialExams/components/AttemptsList.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { DataTable } from '@openedx/paragon';\nimport UsernameFilter from '@src/components/UsernameFilter';\nimport messages from '@src/specialExams/messages';\nimport { useAttempts } from '@src/specialExams/data/apiHook';\nimport { DataTableFetchDataProps } from '@src/types';\n\nexport const ATTEMPTS_PAGE_SIZE = 25;\n\nconst AttemptsList = () => {\n const intl = useIntl();\n const { courseId = '' } = useParams();\n const [filters, setFilters] = useState({ page: 0, emailOrUsername: '' });\n const { data = { results: [], count: 0, numPages: 0 }, isLoading = false } = useAttempts(courseId, {\n ...filters,\n pageSize: ATTEMPTS_PAGE_SIZE\n });\n\n const columns = useMemo(() => [\n { accessor: 'user.username', Header: intl.formatMessage(messages.username), Filter: UsernameFilter, },\n { accessor: 'examName', Header: intl.formatMessage(messages.examName), disableFilters: true, },\n { accessor: 'allowedTimeLimitMins', Header: intl.formatMessage(messages.timeLimit), disableFilters: true, },\n { accessor: 'type', Header: intl.formatMessage(messages.type), disableFilters: true, },\n { accessor: 'startTime', Header: intl.formatMessage(messages.startedAt), disableFilters: true, },\n { accessor: 'endTime', Header: intl.formatMessage(messages.completedAt), disableFilters: true, },\n { accessor: 'status', Header: intl.formatMessage(messages.status), disableFilters: true, },\n ], [intl]);\n\n const handleFetchData = (data: DataTableFetchDataProps) => {\n const emailOrUsernameFilter = data.filters?.find((f) => f.id === 'user.username');\n const newEmailOrUsername = emailOrUsernameFilter ? emailOrUsernameFilter.value : '';\n if (filters.emailOrUsername !== newEmailOrUsername) {\n setFilters((prevFilters) => ({ ...prevFilters, emailOrUsername: newEmailOrUsername, page: 0 }));\n return;\n }\n if (data.pageIndex !== filters.page) {\n setFilters((prevFilters) => ({ ...prevFilters, page: data.pageIndex }));\n }\n };\n\n return (\n <DataTable\n className=\"mt-3\"\n columns={columns}\n data={data.results}\n state={{\n pageIndex: filters.page,\n pageSize: ATTEMPTS_PAGE_SIZE,\n filters: [\n { id: 'emailOrUsername', value: filters.emailOrUsername }\n ]\n }}\n fetchData={handleFetchData}\n isFilterable\n isLoading={isLoading}\n isPaginated\n isSortable\n itemCount={data.count}\n manualFilters\n manualPagination\n manualSortBy\n pageSize={ATTEMPTS_PAGE_SIZE}\n pageCount={data.numPages}\n FilterStatusComponent={() => null}\n >\n <DataTable.TableControlBar className=\"bg-light-200 py-3 px-4\" />\n <DataTable.Table />\n <DataTable.EmptyTable content={intl.formatMessage(messages.noAttempts)} />\n <DataTable.TableFooter />\n </DataTable>\n );\n};\n\nexport default AttemptsList;\n"]}
1
+ {"version":3,"file":"AttemptsList.js","sourceRoot":"","sources":["../../../src/specialExams/components/AttemptsList.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { DataTable } from '@openedx/paragon';\nimport UsernameFilter from '@src/components/UsernameFilter';\nimport messages from '@src/specialExams/messages';\nimport { useAttempts } from '@src/specialExams/data/apiHook';\nimport { DataTableFetchDataProps } from '@src/types';\n\nexport const ATTEMPTS_PAGE_SIZE = 25;\n\nconst AttemptsList = () => {\n const intl = useIntl();\n const { courseId = '' } = useParams();\n const [filters, setFilters] = useState({ page: 0, emailOrUsername: '', ordering: '' });\n const { data = { results: [], count: 0, numPages: 0 }, isLoading = false } = useAttempts(courseId, {\n ...filters,\n pageSize: ATTEMPTS_PAGE_SIZE\n });\n\n const columns = useMemo(() => [\n { accessor: 'user.username', Header: intl.formatMessage(messages.username), Filter: UsernameFilter, },\n { accessor: 'examName', Header: intl.formatMessage(messages.examName), disableFilters: true, },\n { accessor: 'allowedTimeLimitMins', Header: intl.formatMessage(messages.timeLimit), disableFilters: true, },\n { accessor: 'type', Header: intl.formatMessage(messages.type), disableFilters: true, },\n { accessor: 'startTime', Header: intl.formatMessage(messages.startedAt), disableFilters: true, },\n { accessor: 'endTime', Header: intl.formatMessage(messages.completedAt), disableFilters: true, },\n { accessor: 'status', Header: intl.formatMessage(messages.status), disableFilters: true, },\n ], [intl]);\n\n const handleFetchData = (data: DataTableFetchDataProps) => {\n const emailOrUsernameFilter = data.filters?.find((f) => f.id === 'user.username');\n const newEmailOrUsername = emailOrUsernameFilter ? emailOrUsernameFilter.value : '';\n const newOrdering = data.sortBy?.[0] ? `${data.sortBy[0].desc ? '-' : ''}${data.sortBy[0].id}` : '';\n const filtersChanged = newEmailOrUsername !== filters.emailOrUsername || newOrdering !== filters.ordering;\n if (filtersChanged) {\n setFilters((prevFilters) => ({ ...prevFilters, emailOrUsername: newEmailOrUsername, ordering: newOrdering, page: 0 }));\n return;\n }\n if (data.pageIndex !== filters.page) {\n setFilters((prevFilters) => ({ ...prevFilters, page: data.pageIndex }));\n }\n };\n\n return (\n <DataTable\n className=\"mt-3\"\n columns={columns}\n data={data.results}\n state={{\n pageIndex: filters.page,\n pageSize: ATTEMPTS_PAGE_SIZE,\n filters: [\n { id: 'emailOrUsername', value: filters.emailOrUsername }\n ],\n sortBy: [\n { id: filters.ordering.replace(/^-/, ''), desc: filters.ordering.startsWith('-') }\n ]\n }}\n fetchData={handleFetchData}\n isFilterable\n isLoading={isLoading}\n isPaginated\n isSortable\n itemCount={data.count}\n manualFilters\n manualPagination\n manualSortBy\n pageSize={ATTEMPTS_PAGE_SIZE}\n pageCount={data.numPages}\n FilterStatusComponent={() => null}\n >\n <DataTable.TableControlBar className=\"bg-light-200 py-3 px-4\" />\n <DataTable.Table />\n <DataTable.EmptyTable content={intl.formatMessage(messages.noAttempts)} />\n <DataTable.TableFooter />\n </DataTable>\n );\n};\n\nexport default AttemptsList;\n"]}
@@ -56,7 +56,7 @@ const EditAllowanceModal = ({ isOpen, onClose, allowance }) => {
56
56
  if (!(learner === null || learner === void 0 ? void 0 : learner.username)) {
57
57
  return null;
58
58
  }
59
- return (_jsxs(ModalDialog, { isOpen: isOpen, onClose: onClose, title: intl.formatMessage(messages.editAllowance), isOverflowVisible: false, size: "lg", children: [_jsx(ModalDialog.Header, { className: "border-bottom border-light-700", children: _jsx(ModalDialog.Title, { className: "text-primary-700", children: intl.formatMessage(messages.editAllowance) }) }), _jsxs(Form, { className: "position-relative overflow-auto", onSubmit: handleEdit, children: [_jsxs(ModalDialog.Body, { children: [_jsx(Form.Group, { controlId: "learner-info", children: _jsx(SpecifyLearnerField, { learner: learner, onClickSelect: () => { } }) }), _jsxs(Form.Group, { controlId: "select-exam-type", children: [_jsxs(Form.Label, { className: "text-primary-500 x-small", children: [intl.formatMessage(messages.selectExamType), ":"] }), _jsx(Form.Control, { as: "select", disabled: true, children: _jsx("option", { value: "", children: allowance.proctoredExam.examType }) })] }), _jsxs(Form.Group, { controlId: "select-exams", children: [_jsxs(Form.Label, { className: "text-primary-500 x-small", children: [intl.formatMessage(messages.selectExams), ":"] }), _jsx("div", { children: _jsx(Form.Checkbox, { className: "mt-2", checked: true, disabled: true, labelClassName: "text-primary-500", children: allowance.proctoredExam.examName }, allowance.proctoredExam.examName) })] }), _jsxs(Form.Group, { controlId: "select-allowance-type", children: [_jsxs(Form.Label, { className: "text-primary-500 x-small", children: [intl.formatMessage(messages.selectAllowanceType), ":"] }), _jsx(Form.Control, { as: "select", name: "allowanceType", onChange: handleChanges, value: editedAllowance.allowanceType, children: allowanceTypesOptions.map(option => (_jsx("option", { value: option.value, children: intl.formatMessage(option.label) }, option.value))) })] }), _jsxs(Form.Group, { controlId: "allowance-value", children: [_jsxs(Form.Label, { className: "text-primary-500 x-small", children: [intl.formatMessage(addLabel[editedAllowance.allowanceType || 'additional_time_granted']), ":"] }), _jsx(Form.Control, { type: editedAllowance.allowanceType === 'review_policy_exception' ? 'text' : 'number', placeholder: intl.formatMessage(addPlaceholder[editedAllowance.allowanceType || 'additional_time_granted']), name: "value", value: editedAllowance.value, onChange: handleChanges })] })] }), _jsx(ModalDialog.Footer, { className: "border-top border-light-700", children: _jsxs(ActionRow, { children: [_jsx(Button, { variant: "tertiary", onClick: onClose, children: intl.formatMessage(messages.cancel) }), _jsx(Button, { variant: "primary", type: "submit", disabled: !hasChanges, children: intl.formatMessage(messages.editAllowance) })] }) })] })] }));
59
+ return (_jsxs(ModalDialog, { isOpen: isOpen, onClose: onClose, title: intl.formatMessage(messages.editAllowance), isOverflowVisible: false, size: "lg", children: [_jsx(ModalDialog.Header, { className: "border-bottom border-light-700", children: _jsx(ModalDialog.Title, { className: "text-primary-700", children: intl.formatMessage(messages.editAllowance) }) }), _jsxs(Form, { className: "position-relative overflow-auto", onSubmit: handleEdit, children: [_jsxs(ModalDialog.Body, { children: [_jsx(Form.Group, { controlId: "learner-info", children: _jsx(SpecifyLearnerField, { learner: learner, onClickSelect: () => { } }) }), _jsxs(Form.Group, { controlId: "select-exam-type", children: [_jsxs(Form.Label, { className: "text-primary-500 x-small", children: [intl.formatMessage(messages.selectExamType), ":"] }), _jsx(Form.Control, { as: "select", disabled: true, controlClassName: "text-capitalize", children: _jsx("option", { value: "", children: allowance.proctoredExam.examType }) })] }), _jsxs(Form.Group, { controlId: "select-exams", children: [_jsxs(Form.Label, { className: "text-primary-500 x-small", children: [intl.formatMessage(messages.selectExams), ":"] }), _jsx("div", { children: _jsx(Form.Checkbox, { className: "mt-2", checked: true, disabled: true, labelClassName: "text-primary-500", children: allowance.proctoredExam.examName }, allowance.proctoredExam.examName) })] }), _jsxs(Form.Group, { controlId: "select-allowance-type", children: [_jsxs(Form.Label, { className: "text-primary-500 x-small", children: [intl.formatMessage(messages.selectAllowanceType), ":"] }), _jsx(Form.Control, { as: "select", name: "allowanceType", onChange: handleChanges, value: editedAllowance.allowanceType, children: allowanceTypesOptions.map(option => (_jsx("option", { value: option.value, children: intl.formatMessage(option.label) }, option.value))) })] }), _jsxs(Form.Group, { controlId: "allowance-value", children: [_jsxs(Form.Label, { className: "text-primary-500 x-small", children: [intl.formatMessage(addLabel[editedAllowance.allowanceType || 'additional_time_granted']), ":"] }), _jsx(Form.Control, { type: editedAllowance.allowanceType === 'review_policy_exception' ? 'text' : 'number', placeholder: intl.formatMessage(addPlaceholder[editedAllowance.allowanceType || 'additional_time_granted']), name: "value", value: editedAllowance.value, onChange: handleChanges })] })] }), _jsx(ModalDialog.Footer, { className: "border-top border-light-700", children: _jsxs(ActionRow, { children: [_jsx(Button, { variant: "tertiary", onClick: onClose, children: intl.formatMessage(messages.cancel) }), _jsx(Button, { variant: "primary", type: "submit", disabled: !hasChanges, children: intl.formatMessage(messages.editAllowance) })] }) })] })] }));
60
60
  };
61
61
  export default EditAllowanceModal;
62
62
  //# sourceMappingURL=EditAllowanceModal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditAllowanceModal.js","sourceRoot":"","sources":["../../../src/specialExams/components/EditAllowanceModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { ActionRow, Button, Form, ModalDialog } from '@openedx/paragon';\nimport SpecifyLearnerField from '@src/components/SpecifyLearnerField';\nimport { useLearner } from '@src/data/apiHook';\nimport { addLabel, addPlaceholder, allowanceTypesOptions } from '@src/specialExams/constants';\nimport { useAddAllowance } from '@src/specialExams/data/apiHook';\nimport messages from '@src/specialExams/messages';\nimport { Allowance } from '@src/specialExams/types';\nimport { useAlert } from '@src/providers/AlertProvider';\n\ninterface EditAllowanceModalProps {\n isOpen: boolean,\n onClose: () => void,\n allowance: Allowance,\n}\n\nconst EditAllowanceModal = ({ isOpen, onClose, allowance }: EditAllowanceModalProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const { mutate: editAllowance } = useAddAllowance(courseId);\n const { data: learner, refetch } = useLearner(courseId, allowance.user.username);\n const [editedAllowance, setEditedAllowance] = useState({\n allowanceType: allowance.key,\n value: allowance.value,\n });\n const { showModal } = useAlert();\n\n useEffect(() => {\n if (isOpen) {\n // Refetch learner data when modal opens to ensure we have the most up-to-date information\n refetch();\n }\n }, [isOpen, refetch]);\n\n const handleChanges = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {\n const { name, value } = e.target;\n setEditedAllowance(prev => ({ ...prev, [name]: value }));\n };\n\n const hasChanges = useMemo(() => {\n return (editedAllowance.allowanceType !== allowance.key && editedAllowance.allowanceType !== '')\n || editedAllowance.value !== allowance.value;\n }, [editedAllowance, allowance]);\n\n const handleEdit = (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault();\n editAllowance({\n examType: allowance.proctoredExam.examType,\n allowanceType: editedAllowance.allowanceType,\n value: editedAllowance.value,\n userIds: [allowance.user.username],\n examIds: [allowance.proctoredExam.id],\n }, {\n onSuccess: () => {\n onClose();\n },\n onError: () => {\n showModal({\n message: intl.formatMessage(messages.editAllowanceError),\n variant: 'danger',\n });\n }\n });\n };\n\n if (!learner?.username) {\n return null;\n }\n\n return (\n <ModalDialog isOpen={isOpen} onClose={onClose} title={intl.formatMessage(messages.editAllowance)} isOverflowVisible={false} size=\"lg\">\n <ModalDialog.Header className=\"border-bottom border-light-700\">\n <ModalDialog.Title className=\"text-primary-700\">{intl.formatMessage(messages.editAllowance)}</ModalDialog.Title>\n </ModalDialog.Header>\n <Form className=\"position-relative overflow-auto\" onSubmit={handleEdit}>\n <ModalDialog.Body>\n <Form.Group controlId=\"learner-info\">\n <SpecifyLearnerField learner={learner} onClickSelect={() => {}} />\n </Form.Group>\n <Form.Group controlId=\"select-exam-type\">\n <Form.Label className=\"text-primary-500 x-small\">{intl.formatMessage(messages.selectExamType)}:</Form.Label>\n <Form.Control as=\"select\" disabled>\n <option value=\"\">{allowance.proctoredExam.examType}</option>\n </Form.Control>\n </Form.Group>\n <Form.Group controlId=\"select-exams\">\n <Form.Label className=\"text-primary-500 x-small\">{intl.formatMessage(messages.selectExams)}:</Form.Label>\n <div>\n <Form.Checkbox className=\"mt-2\" key={allowance.proctoredExam.examName} checked disabled labelClassName=\"text-primary-500\">\n {allowance.proctoredExam.examName}\n </Form.Checkbox>\n </div>\n </Form.Group>\n <Form.Group controlId=\"select-allowance-type\">\n <Form.Label className=\"text-primary-500 x-small\">{intl.formatMessage(messages.selectAllowanceType)}:</Form.Label>\n <Form.Control as=\"select\" name=\"allowanceType\" onChange={handleChanges} value={editedAllowance.allowanceType}>\n {allowanceTypesOptions.map(option => (\n <option key={option.value} value={option.value}>{intl.formatMessage(option.label)}</option>\n ))}\n </Form.Control>\n </Form.Group>\n <Form.Group controlId=\"allowance-value\">\n <Form.Label className=\"text-primary-500 x-small\">{intl.formatMessage(addLabel[editedAllowance.allowanceType || 'additional_time_granted'])}:</Form.Label>\n <Form.Control\n type={editedAllowance.allowanceType === 'review_policy_exception' ? 'text' : 'number'}\n placeholder={intl.formatMessage(addPlaceholder[editedAllowance.allowanceType || 'additional_time_granted'])}\n name=\"value\"\n value={editedAllowance.value}\n onChange={handleChanges}\n />\n </Form.Group>\n </ModalDialog.Body>\n <ModalDialog.Footer className=\"border-top border-light-700\">\n <ActionRow>\n <Button variant=\"tertiary\" onClick={onClose}>{intl.formatMessage(messages.cancel)}</Button>\n <Button variant=\"primary\" type=\"submit\" disabled={!hasChanges}>{intl.formatMessage(messages.editAllowance)}</Button>\n </ActionRow>\n </ModalDialog.Footer>\n </Form>\n </ModalDialog>\n );\n};\n\nexport default EditAllowanceModal;\n"]}
1
+ {"version":3,"file":"EditAllowanceModal.js","sourceRoot":"","sources":["../../../src/specialExams/components/EditAllowanceModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,mBAAmB,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAC9F,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,QAAQ,MAAM,4BAA4B,CAAC;AAElD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAQxD,MAAM,kBAAkB,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAA2B,EAAE,EAAE;IACrF,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,SAAS,EAAwB,CAAC;IAC5D,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC5D,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjF,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAC;QACrD,aAAa,EAAE,SAAS,CAAC,GAAG;QAC5B,KAAK,EAAE,SAAS,CAAC,KAAK;KACvB,CAAC,CAAC;IACH,MAAM,EAAE,SAAS,EAAE,GAAG,QAAQ,EAAE,CAAC;IAEjC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,EAAE,CAAC;YACX,0FAA0F;YAC1F,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAEtB,MAAM,aAAa,GAAG,CAAC,CAA0D,EAAE,EAAE;QACnF,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC;QACjC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,iCAAM,IAAI,KAAE,CAAC,IAAI,CAAC,EAAE,KAAK,IAAG,CAAC,CAAC;IAC3D,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE;QAC9B,OAAO,CAAC,eAAe,CAAC,aAAa,KAAK,SAAS,CAAC,GAAG,IAAI,eAAe,CAAC,aAAa,KAAK,EAAE,CAAC;eAC3F,eAAe,CAAC,KAAK,KAAK,SAAS,CAAC,KAAK,CAAC;IACjD,CAAC,EAAE,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC,CAAC;IAEjC,MAAM,UAAU,GAAG,CAAC,CAAmC,EAAE,EAAE;QACzD,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,aAAa,CAAC;YACZ,QAAQ,EAAE,SAAS,CAAC,aAAa,CAAC,QAAQ;YAC1C,aAAa,EAAE,eAAe,CAAC,aAAa;YAC5C,KAAK,EAAE,eAAe,CAAC,KAAK;YAC5B,OAAO,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC;YAClC,OAAO,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC;SACtC,EAAE;YACD,SAAS,EAAE,GAAG,EAAE;gBACd,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,OAAO,EAAE,GAAG,EAAE;gBACZ,SAAS,CAAC;oBACR,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,kBAAkB,CAAC;oBACxD,OAAO,EAAE,QAAQ;iBAClB,CAAC,CAAC;YACL,CAAC;SACF,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,IAAI,CAAC,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,CAAA,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,MAAC,WAAW,IAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,iBAAiB,EAAE,KAAK,EAAE,IAAI,EAAC,IAAI,aACnI,KAAC,WAAW,CAAC,MAAM,IAAC,SAAS,EAAC,gCAAgC,YAC5D,KAAC,WAAW,CAAC,KAAK,IAAC,SAAS,EAAC,kBAAkB,YAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAqB,GAC7F,EACrB,MAAC,IAAI,IAAC,SAAS,EAAC,iCAAiC,EAAC,QAAQ,EAAE,UAAU,aACpE,MAAC,WAAW,CAAC,IAAI,eACf,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,cAAc,YAClC,KAAC,mBAAmB,IAAC,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,GAAE,CAAC,GAAI,GACvD,EACb,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,kBAAkB,aACtC,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,0BAA0B,aAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,SAAe,EAC5G,KAAC,IAAI,CAAC,OAAO,IAAC,EAAE,EAAC,QAAQ,EAAC,QAAQ,QAAC,gBAAgB,EAAC,iBAAiB,YACnE,iBAAQ,KAAK,EAAC,EAAE,YAAE,SAAS,CAAC,aAAa,CAAC,QAAQ,GAAU,GAC/C,IACJ,EACb,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,cAAc,aAClC,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,0BAA0B,aAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAe,EACzG,wBACE,KAAC,IAAI,CAAC,QAAQ,IAAC,SAAS,EAAC,MAAM,EAAwC,OAAO,QAAC,QAAQ,QAAC,cAAc,EAAC,kBAAkB,YACtH,SAAS,CAAC,aAAa,CAAC,QAAQ,IADE,SAAS,CAAC,aAAa,CAAC,QAAQ,CAErD,GACZ,IACK,EACb,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,uBAAuB,aAC3C,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,0BAA0B,aAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAe,EACjH,KAAC,IAAI,CAAC,OAAO,IAAC,EAAE,EAAC,QAAQ,EAAC,IAAI,EAAC,eAAe,EAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,eAAe,CAAC,aAAa,YACzG,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CACnC,iBAA2B,KAAK,EAAE,MAAM,CAAC,KAAK,YAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,IAApE,MAAM,CAAC,KAAK,CAAkE,CAC5F,CAAC,GACW,IACJ,EACb,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,iBAAiB,aACrC,MAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,0BAA0B,aAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,eAAe,CAAC,aAAa,IAAI,yBAAyB,CAAC,CAAC,SAAe,EACzJ,KAAC,IAAI,CAAC,OAAO,IACX,IAAI,EAAE,eAAe,CAAC,aAAa,KAAK,yBAAyB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EACrF,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,eAAe,CAAC,aAAa,IAAI,yBAAyB,CAAC,CAAC,EAC3G,IAAI,EAAC,OAAO,EACZ,KAAK,EAAE,eAAe,CAAC,KAAK,EAC5B,QAAQ,EAAE,aAAa,GACvB,IACS,IACI,EACnB,KAAC,WAAW,CAAC,MAAM,IAAC,SAAS,EAAC,6BAA6B,YACzD,MAAC,SAAS,eACR,KAAC,MAAM,IAAC,OAAO,EAAC,UAAU,EAAC,OAAO,EAAE,OAAO,YAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAU,EAC3F,KAAC,MAAM,IAAC,OAAO,EAAC,SAAS,EAAC,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,UAAU,YAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAU,IAC1G,GACO,IAChB,IACK,CACf,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,kBAAkB,CAAC","sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { ActionRow, Button, Form, ModalDialog } from '@openedx/paragon';\nimport SpecifyLearnerField from '@src/components/SpecifyLearnerField';\nimport { useLearner } from '@src/data/apiHook';\nimport { addLabel, addPlaceholder, allowanceTypesOptions } from '@src/specialExams/constants';\nimport { useAddAllowance } from '@src/specialExams/data/apiHook';\nimport messages from '@src/specialExams/messages';\nimport { Allowance } from '@src/specialExams/types';\nimport { useAlert } from '@src/providers/AlertProvider';\n\ninterface EditAllowanceModalProps {\n isOpen: boolean,\n onClose: () => void,\n allowance: Allowance,\n}\n\nconst EditAllowanceModal = ({ isOpen, onClose, allowance }: EditAllowanceModalProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const { mutate: editAllowance } = useAddAllowance(courseId);\n const { data: learner, refetch } = useLearner(courseId, allowance.user.username);\n const [editedAllowance, setEditedAllowance] = useState({\n allowanceType: allowance.key,\n value: allowance.value,\n });\n const { showModal } = useAlert();\n\n useEffect(() => {\n if (isOpen) {\n // Refetch learner data when modal opens to ensure we have the most up-to-date information\n refetch();\n }\n }, [isOpen, refetch]);\n\n const handleChanges = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {\n const { name, value } = e.target;\n setEditedAllowance(prev => ({ ...prev, [name]: value }));\n };\n\n const hasChanges = useMemo(() => {\n return (editedAllowance.allowanceType !== allowance.key && editedAllowance.allowanceType !== '')\n || editedAllowance.value !== allowance.value;\n }, [editedAllowance, allowance]);\n\n const handleEdit = (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault();\n editAllowance({\n examType: allowance.proctoredExam.examType,\n allowanceType: editedAllowance.allowanceType,\n value: editedAllowance.value,\n userIds: [allowance.user.username],\n examIds: [allowance.proctoredExam.id],\n }, {\n onSuccess: () => {\n onClose();\n },\n onError: () => {\n showModal({\n message: intl.formatMessage(messages.editAllowanceError),\n variant: 'danger',\n });\n }\n });\n };\n\n if (!learner?.username) {\n return null;\n }\n\n return (\n <ModalDialog isOpen={isOpen} onClose={onClose} title={intl.formatMessage(messages.editAllowance)} isOverflowVisible={false} size=\"lg\">\n <ModalDialog.Header className=\"border-bottom border-light-700\">\n <ModalDialog.Title className=\"text-primary-700\">{intl.formatMessage(messages.editAllowance)}</ModalDialog.Title>\n </ModalDialog.Header>\n <Form className=\"position-relative overflow-auto\" onSubmit={handleEdit}>\n <ModalDialog.Body>\n <Form.Group controlId=\"learner-info\">\n <SpecifyLearnerField learner={learner} onClickSelect={() => {}} />\n </Form.Group>\n <Form.Group controlId=\"select-exam-type\">\n <Form.Label className=\"text-primary-500 x-small\">{intl.formatMessage(messages.selectExamType)}:</Form.Label>\n <Form.Control as=\"select\" disabled controlClassName=\"text-capitalize\">\n <option value=\"\">{allowance.proctoredExam.examType}</option>\n </Form.Control>\n </Form.Group>\n <Form.Group controlId=\"select-exams\">\n <Form.Label className=\"text-primary-500 x-small\">{intl.formatMessage(messages.selectExams)}:</Form.Label>\n <div>\n <Form.Checkbox className=\"mt-2\" key={allowance.proctoredExam.examName} checked disabled labelClassName=\"text-primary-500\">\n {allowance.proctoredExam.examName}\n </Form.Checkbox>\n </div>\n </Form.Group>\n <Form.Group controlId=\"select-allowance-type\">\n <Form.Label className=\"text-primary-500 x-small\">{intl.formatMessage(messages.selectAllowanceType)}:</Form.Label>\n <Form.Control as=\"select\" name=\"allowanceType\" onChange={handleChanges} value={editedAllowance.allowanceType}>\n {allowanceTypesOptions.map(option => (\n <option key={option.value} value={option.value}>{intl.formatMessage(option.label)}</option>\n ))}\n </Form.Control>\n </Form.Group>\n <Form.Group controlId=\"allowance-value\">\n <Form.Label className=\"text-primary-500 x-small\">{intl.formatMessage(addLabel[editedAllowance.allowanceType || 'additional_time_granted'])}:</Form.Label>\n <Form.Control\n type={editedAllowance.allowanceType === 'review_policy_exception' ? 'text' : 'number'}\n placeholder={intl.formatMessage(addPlaceholder[editedAllowance.allowanceType || 'additional_time_granted'])}\n name=\"value\"\n value={editedAllowance.value}\n onChange={handleChanges}\n />\n </Form.Group>\n </ModalDialog.Body>\n <ModalDialog.Footer className=\"border-top border-light-700\">\n <ActionRow>\n <Button variant=\"tertiary\" onClick={onClose}>{intl.formatMessage(messages.cancel)}</Button>\n <Button variant=\"primary\" type=\"submit\" disabled={!hasChanges}>{intl.formatMessage(messages.editAllowance)}</Button>\n </ActionRow>\n </ModalDialog.Footer>\n </Form>\n </ModalDialog>\n );\n};\n\nexport default EditAllowanceModal;\n"]}
@@ -8,6 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { getAuthenticatedHttpClient, camelCaseObject, snakeCaseObject } from '@openedx/frontend-base';
11
+ import { snakeCase } from 'lodash';
11
12
  import { getApiBaseUrl } from '../../data/api';
12
13
  const getQueryParams = (params) => {
13
14
  const queryParams = new URLSearchParams({
@@ -17,6 +18,11 @@ const getQueryParams = (params) => {
17
18
  if (params.emailOrUsername) {
18
19
  queryParams.append('search', params.emailOrUsername);
19
20
  }
21
+ if (params.ordering) {
22
+ const hasNegativePrefix = params.ordering.startsWith('-');
23
+ const orderingParam = params.ordering.split('.').map((part) => snakeCase(part)).join('.');
24
+ queryParams.append('ordering', `${hasNegativePrefix ? '-' : ''}${orderingParam}`);
25
+ }
20
26
  return queryParams;
21
27
  };
22
28
  export const getAttempts = (courseId, params) => __awaiter(void 0, void 0, void 0, function* () {
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/specialExams/data/api.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,0BAA0B,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACtG,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI9C,MAAM,cAAc,GAAG,CAAC,MAAsB,EAAE,EAAE;IAChD,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC;QACtC,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE;QAClC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE;KACtC,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QAC3B,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAO,QAAgB,EAAE,MAAsB,EAA8B,EAAE;IACxG,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAE3C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CACrD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,2BAA2B,WAAW,CAAC,QAAQ,EAAE,EAAE,CAC5G,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAO,QAAgB,EAAE,MAAsB,EAAgC,EAAE;IAC5G,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAE3C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CACrD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,6BAA6B,WAAW,CAAC,QAAQ,EAAE,EAAE,CAC9G,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAO,QAAgB,EAAE,YAAgC,EAAwB,EAAE;IAC7G,MAAM,qBAAqB,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;IAC5D,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,IAAI,CACtD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,2BAA2B,EACnF,qBAAqB,CACtB,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAO,QAAgB,EAAE,MAA6B,EAAiB,EAAE;IACtG,MAAM,eAAe,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,0BAA0B,EAAE,CAAC,MAAM,CACvC,GAAG,aAAa,EAAE,8BAA8B,QAAQ,kBAAkB,MAAM,CAAC,MAAM,YAAY,EAAE;QACnG,IAAI,EAAE,eAAe;KACtB,CACF,CAAC;AACJ,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAO,QAAgB,EAAE,QAAgB,EAA0B,EAAE;IAClG,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CACrD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,gBAAgB,EAAE;QACxE,MAAM,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE;KAChC,CACF,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC","sourcesContent":["import { getAuthenticatedHttpClient, camelCaseObject, snakeCaseObject } from '@openedx/frontend-base';\nimport { getApiBaseUrl } from '@src/data/api';\nimport { DataList } from '@src/types';\nimport { AddAllowanceParams, Allowance, Attempt, AttemptsParams, DeleteAllowanceParams, SpecialExam } from '../types';\n\nconst getQueryParams = (params: AttemptsParams) => {\n const queryParams = new URLSearchParams({\n page: (params.page + 1).toString(),\n page_size: params.pageSize.toString(),\n });\n\n if (params.emailOrUsername) {\n queryParams.append('search', params.emailOrUsername);\n }\n\n return queryParams;\n};\n\nexport const getAttempts = async (courseId: string, params: AttemptsParams): Promise<DataList<Attempt>> => {\n const queryParams = getQueryParams(params);\n\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/special_exams/attempts?${queryParams.toString()}`\n );\n return camelCaseObject(data);\n};\n\nexport const getAllowances = async (courseId: string, params: AttemptsParams): Promise<DataList<Allowance>> => {\n const queryParams = getQueryParams(params);\n\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/special_exams/allowances?${queryParams.toString()}`\n );\n return camelCaseObject(data);\n};\n\nexport const addAllowance = async (courseId: string, newAllowance: AddAllowanceParams): Promise<Allowance[]> => {\n const newAllowanceSnakeCase = snakeCaseObject(newAllowance);\n const { data } = await getAuthenticatedHttpClient().post(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/special_exams/allowances`,\n newAllowanceSnakeCase\n );\n return camelCaseObject(data);\n};\n\nexport const deleteAllowance = async (courseId: string, params: DeleteAllowanceParams): Promise<void> => {\n const snakeCaseParams = snakeCaseObject(params);\n await getAuthenticatedHttpClient().delete(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/special_exams/${params.examId}/allowance`, {\n data: snakeCaseParams\n }\n );\n};\n\nexport const getSpecialExams = async (courseId: string, examType: string): Promise<SpecialExam[]> => {\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/special_exams`, {\n params: { exam_type: examType }\n }\n );\n return camelCaseObject(data);\n};\n"]}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/specialExams/data/api.ts"],"names":[],"mappings":"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","sourcesContent":["import { getAuthenticatedHttpClient, camelCaseObject, snakeCaseObject } from '@openedx/frontend-base';\nimport { snakeCase } from 'lodash';\nimport { getApiBaseUrl } from '@src/data/api';\nimport { DataList } from '@src/types';\nimport { AddAllowanceParams, Allowance, Attempt, AttemptsParams, DeleteAllowanceParams, SpecialExam } from '../types';\n\nconst getQueryParams = (params: AttemptsParams) => {\n const queryParams = new URLSearchParams({\n page: (params.page + 1).toString(),\n page_size: params.pageSize.toString(),\n });\n\n if (params.emailOrUsername) {\n queryParams.append('search', params.emailOrUsername);\n }\n\n if (params.ordering) {\n const hasNegativePrefix = params.ordering.startsWith('-');\n\n const orderingParam = params.ordering.split('.').map((part) => snakeCase(part)).join('.');\n\n queryParams.append('ordering', `${hasNegativePrefix ? '-' : ''}${orderingParam}`);\n }\n\n return queryParams;\n};\n\nexport const getAttempts = async (courseId: string, params: AttemptsParams): Promise<DataList<Attempt>> => {\n const queryParams = getQueryParams(params);\n\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/special_exams/attempts?${queryParams.toString()}`\n );\n return camelCaseObject(data);\n};\n\nexport const getAllowances = async (courseId: string, params: AttemptsParams): Promise<DataList<Allowance>> => {\n const queryParams = getQueryParams(params);\n\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/special_exams/allowances?${queryParams.toString()}`\n );\n return camelCaseObject(data);\n};\n\nexport const addAllowance = async (courseId: string, newAllowance: AddAllowanceParams): Promise<Allowance[]> => {\n const newAllowanceSnakeCase = snakeCaseObject(newAllowance);\n const { data } = await getAuthenticatedHttpClient().post(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/special_exams/allowances`,\n newAllowanceSnakeCase\n );\n return camelCaseObject(data);\n};\n\nexport const deleteAllowance = async (courseId: string, params: DeleteAllowanceParams): Promise<void> => {\n const snakeCaseParams = snakeCaseObject(params);\n await getAuthenticatedHttpClient().delete(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/special_exams/${params.examId}/allowance`, {\n data: snakeCaseParams\n }\n );\n};\n\nexport const getSpecialExams = async (courseId: string, examType: string): Promise<SpecialExam[]> => {\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/special_exams`, {\n params: { exam_type: examType }\n }\n );\n return camelCaseObject(data);\n};\n"]}
@@ -2,7 +2,7 @@ import { AttemptsParams } from '../types';
2
2
  export declare const specialExamsQueryKeys: {
3
3
  all: readonly ["org.openedx.frontend.app.instructorDashboard", "specialExams"];
4
4
  byCourse: (courseId: string) => readonly ["org.openedx.frontend.app.instructorDashboard", "specialExams", string];
5
- attempts: (courseId: string, params: AttemptsParams) => readonly ["org.openedx.frontend.app.instructorDashboard", "specialExams", string, "attempts", number, string];
6
- allowances: (courseId: string, params?: AttemptsParams) => readonly ["org.openedx.frontend.app.instructorDashboard", "specialExams", string, "allowances", number, string];
5
+ attempts: (courseId: string, params: AttemptsParams) => readonly ["org.openedx.frontend.app.instructorDashboard", "specialExams", string, "attempts", number, string, string];
6
+ allowances: (courseId: string, params?: AttemptsParams) => readonly ["org.openedx.frontend.app.instructorDashboard", "specialExams", string, "allowances", number, string, string];
7
7
  specialExams: (courseId: string, examType: string) => readonly ["org.openedx.frontend.app.instructorDashboard", "specialExams", string, "specialExams", string];
8
8
  };
@@ -2,8 +2,8 @@ import { appId } from '../../constants';
2
2
  export const specialExamsQueryKeys = {
3
3
  all: [appId, 'specialExams'],
4
4
  byCourse: (courseId) => [...specialExamsQueryKeys.all, courseId],
5
- attempts: (courseId, params) => [...specialExamsQueryKeys.byCourse(courseId), 'attempts', params.page, params.emailOrUsername],
6
- allowances: (courseId, params) => [...specialExamsQueryKeys.byCourse(courseId), 'allowances', (params === null || params === void 0 ? void 0 : params.page) || 1, (params === null || params === void 0 ? void 0 : params.emailOrUsername) || ''],
5
+ attempts: (courseId, params) => [...specialExamsQueryKeys.byCourse(courseId), 'attempts', params.page, params.emailOrUsername, params.ordering],
6
+ allowances: (courseId, params) => [...specialExamsQueryKeys.byCourse(courseId), 'allowances', (params === null || params === void 0 ? void 0 : params.page) || 1, (params === null || params === void 0 ? void 0 : params.emailOrUsername) || '', (params === null || params === void 0 ? void 0 : params.ordering) || ''],
7
7
  specialExams: (courseId, examType) => [...specialExamsQueryKeys.byCourse(courseId), 'specialExams', examType],
8
8
  };
9
9
  //# sourceMappingURL=queryKeys.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"queryKeys.js","sourceRoot":"","sources":["../../../src/specialExams/data/queryKeys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,GAAG,EAAE,CAAC,KAAK,EAAE,cAAc,CAAU;IACrC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,qBAAqB,CAAC,GAAG,EAAE,QAAQ,CAAU;IACjF,QAAQ,EAAE,CAAC,QAAgB,EAAE,MAAsB,EAAE,EAAE,CAAC,CAAC,GAAG,qBAAqB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,eAAe,CAAU;IAC/J,UAAU,EAAE,CAAC,QAAgB,EAAE,MAAuB,EAAE,EAAE,CAAC,CAAC,GAAG,qBAAqB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,KAAI,CAAC,EAAE,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,eAAe,KAAI,EAAE,CAAU;IACjL,YAAY,EAAE,CAAC,QAAgB,EAAE,QAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,qBAAqB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,EAAE,QAAQ,CAAU;CACvI,CAAC","sourcesContent":["import { appId } from '@src/constants';\nimport { AttemptsParams } from '../types';\n\nexport const specialExamsQueryKeys = {\n all: [appId, 'specialExams'] as const,\n byCourse: (courseId: string) => [...specialExamsQueryKeys.all, courseId] as const,\n attempts: (courseId: string, params: AttemptsParams) => [...specialExamsQueryKeys.byCourse(courseId), 'attempts', params.page, params.emailOrUsername] as const,\n allowances: (courseId: string, params?: AttemptsParams) => [...specialExamsQueryKeys.byCourse(courseId), 'allowances', params?.page || 1, params?.emailOrUsername || ''] as const,\n specialExams: (courseId: string, examType: string) => [...specialExamsQueryKeys.byCourse(courseId), 'specialExams', examType] as const,\n};\n"]}
1
+ {"version":3,"file":"queryKeys.js","sourceRoot":"","sources":["../../../src/specialExams/data/queryKeys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,GAAG,EAAE,CAAC,KAAK,EAAE,cAAc,CAAU;IACrC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,qBAAqB,CAAC,GAAG,EAAE,QAAQ,CAAU;IACjF,QAAQ,EAAE,CAAC,QAAgB,EAAE,MAAsB,EAAE,EAAE,CAAC,CAAC,GAAG,qBAAqB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,QAAQ,CAAU;IAChL,UAAU,EAAE,CAAC,QAAgB,EAAE,MAAuB,EAAE,EAAE,CAAC,CAAC,GAAG,qBAAqB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,KAAI,CAAC,EAAE,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,eAAe,KAAI,EAAE,EAAE,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,QAAQ,KAAI,EAAE,CAAU;IACzM,YAAY,EAAE,CAAC,QAAgB,EAAE,QAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,qBAAqB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,EAAE,QAAQ,CAAU;CACvI,CAAC","sourcesContent":["import { appId } from '@src/constants';\nimport { AttemptsParams } from '../types';\n\nexport const specialExamsQueryKeys = {\n all: [appId, 'specialExams'] as const,\n byCourse: (courseId: string) => [...specialExamsQueryKeys.all, courseId] as const,\n attempts: (courseId: string, params: AttemptsParams) => [...specialExamsQueryKeys.byCourse(courseId), 'attempts', params.page, params.emailOrUsername, params.ordering] as const,\n allowances: (courseId: string, params?: AttemptsParams) => [...specialExamsQueryKeys.byCourse(courseId), 'allowances', params?.page || 1, params?.emailOrUsername || '', params?.ordering || ''] as const,\n specialExams: (courseId: string, examType: string) => [...specialExamsQueryKeys.byCourse(courseId), 'specialExams', examType] as const,\n};\n"]}
@@ -14,6 +14,7 @@ export interface Attempt {
14
14
  }
15
15
  export interface AttemptsParams extends PaginationParams {
16
16
  emailOrUsername: string;
17
+ ordering: string;
17
18
  }
18
19
  export interface Allowance {
19
20
  value: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/specialExams/types.ts"],"names":[],"mappings":"","sourcesContent":["import { PaginationParams } from '@src/types';\n\nexport interface Attempt {\n id: number,\n user: {\n username: string,\n },\n examId: number,\n examName: string,\n allowedTimeLimitMins: number,\n type: string,\n startTime: string,\n endTime: string,\n status: string,\n}\n\nexport interface AttemptsParams extends PaginationParams {\n emailOrUsername: string,\n}\n\nexport interface Allowance {\n value: string,\n key: string,\n proctoredExam: {\n examName: string,\n examType: string,\n id: number,\n },\n user: {\n username: string,\n email: string,\n id: number,\n },\n id: number,\n}\n\nexport interface AddAllowanceParams {\n userIds: string[],\n examType: string,\n examIds: number[],\n allowanceType: string,\n value: string,\n}\n\nexport interface AddAllowanceForm {\n users: string,\n examType: string,\n examIds: number[],\n allowanceType: string,\n value: string,\n}\n\nexport interface SpecialExam {\n examName: string,\n examType: string,\n timeLimitMins: number,\n contentId: string,\n courseId: string,\n dueDate: string | null,\n isProctored: boolean,\n isActive: boolean,\n isPracticeExam: boolean,\n hideAfterDue: boolean,\n id: number,\n}\n\nexport interface DeleteAllowanceParams {\n examId: number,\n userIds: number[],\n allowanceType: string,\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/specialExams/types.ts"],"names":[],"mappings":"","sourcesContent":["import { PaginationParams } from '@src/types';\n\nexport interface Attempt {\n id: number,\n user: {\n username: string,\n },\n examId: number,\n examName: string,\n allowedTimeLimitMins: number,\n type: string,\n startTime: string,\n endTime: string,\n status: string,\n}\n\nexport interface AttemptsParams extends PaginationParams {\n emailOrUsername: string,\n ordering: string,\n}\n\nexport interface Allowance {\n value: string,\n key: string,\n proctoredExam: {\n examName: string,\n examType: string,\n id: number,\n },\n user: {\n username: string,\n email: string,\n id: number,\n },\n id: number,\n}\n\nexport interface AddAllowanceParams {\n userIds: string[],\n examType: string,\n examIds: number[],\n allowanceType: string,\n value: string,\n}\n\nexport interface AddAllowanceForm {\n users: string,\n examType: string,\n examIds: number[],\n allowanceType: string,\n value: string,\n}\n\nexport interface SpecialExam {\n examName: string,\n examType: string,\n timeLimitMins: number,\n contentId: string,\n courseId: string,\n dueDate: string | null,\n isProctored: boolean,\n isActive: boolean,\n isPracticeExam: boolean,\n hideAfterDue: boolean,\n id: number,\n}\n\nexport interface DeleteAllowanceParams {\n examId: number,\n userIds: number[],\n allowanceType: string,\n}\n"]}
@@ -37,6 +37,10 @@ export interface DataTableFetchDataProps {
37
37
  value: string;
38
38
  }[];
39
39
  pageIndex: number;
40
+ sortBy: {
41
+ id: string;
42
+ desc: boolean;
43
+ }[];
40
44
  }
41
45
  export interface Learner {
42
46
  username: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAiBC,CAAC;AAMD,CAAC;AAwBD,CAAC","sourcesContent":["export interface TableCellValue<T> {\n row: {\n original: T,\n },\n}\n\nexport interface PaginationParams {\n page: number,\n pageSize: number,\n}\n\nexport interface APIError {\n response: {\n data: {\n error: string,\n },\n },\n};\n\nexport interface DataList<T> {\n count: number,\n numPages: number,\n results: T[],\n};\n\nexport interface PendingTask {\n taskType: string,\n taskInput: Record<string, any>,\n taskId: string,\n requester: string,\n taskState: string,\n created: string,\n taskOutput: Record<string, any> | null,\n durationSec: number,\n status: string,\n taskMessage: string,\n}\n\nexport interface DataTableFetchDataProps {\n filters: { id: string, value: string }[],\n pageIndex: number,\n}\n\nexport interface Learner {\n username: string,\n fullName: string,\n email: string,\n};\n\nexport interface SelectedLearner extends Learner {\n progressUrl: string,\n isEnrolled: boolean,\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAiBC,CAAC;AAMD,CAAC;AAyBD,CAAC","sourcesContent":["export interface TableCellValue<T> {\n row: {\n original: T,\n },\n}\n\nexport interface PaginationParams {\n page: number,\n pageSize: number,\n}\n\nexport interface APIError {\n response: {\n data: {\n error: string,\n },\n },\n};\n\nexport interface DataList<T> {\n count: number,\n numPages: number,\n results: T[],\n};\n\nexport interface PendingTask {\n taskType: string,\n taskInput: Record<string, any>,\n taskId: string,\n requester: string,\n taskState: string,\n created: string,\n taskOutput: Record<string, any> | null,\n durationSec: number,\n status: string,\n taskMessage: string,\n}\n\nexport interface DataTableFetchDataProps {\n filters: { id: string, value: string }[],\n pageIndex: number,\n sortBy: { id: string, desc: boolean }[],\n}\n\nexport interface Learner {\n username: string,\n fullName: string,\n email: string,\n};\n\nexport interface SelectedLearner extends Learner {\n progressUrl: string,\n isEnrolled: boolean,\n}\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.33",
3
+ "version": "1.0.0-alpha.34",
4
4
  "description": "The Open edX Instructor Dashboard",
5
5
  "repository": {
6
6
  "type": "git",