@openedx/frontend-app-instructor-dashboard 1.0.0-alpha.21 → 1.0.0-alpha.23
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.
- package/dist/courseTeam/components/AddTeamMemberModal.js +2 -1
- package/dist/courseTeam/components/AddTeamMemberModal.js.map +1 -1
- package/dist/courseTeam/components/EditTeamMemberModal.js +3 -2
- package/dist/courseTeam/components/EditTeamMemberModal.js.map +1 -1
- package/dist/courseTeam/constants.d.ts +3 -0
- package/dist/courseTeam/constants.js +4 -0
- package/dist/courseTeam/constants.js.map +1 -0
- package/dist/courseTeam/data/api.d.ts +2 -2
- package/dist/courseTeam/data/api.js +2 -2
- package/dist/courseTeam/data/api.js.map +1 -1
- package/dist/courseTeam/data/apiHook.d.ts +2 -5
- package/dist/courseTeam/data/apiHook.js +1 -1
- package/dist/courseTeam/data/apiHook.js.map +1 -1
- package/dist/courseTeam/types.d.ts +7 -0
- package/dist/courseTeam/types.js.map +1 -1
- package/dist/dateExtensions/components/AddExtensionModal.js +1 -1
- package/dist/dateExtensions/components/AddExtensionModal.js.map +1 -1
- package/dist/dateExtensions/components/DateExtensionsList.js +1 -1
- package/dist/dateExtensions/components/DateExtensionsList.js.map +1 -1
- package/package.json +2 -1
|
@@ -8,6 +8,7 @@ import messages from '../../courseTeam/messages';
|
|
|
8
8
|
import { useCourseInfo } from '../../data/apiHook';
|
|
9
9
|
import { useDebouncedFilter } from '../../hooks/useDebouncedFilter';
|
|
10
10
|
import { useAlert } from '../../providers/AlertProvider';
|
|
11
|
+
import { TEAM_MEMBER_ACTION } from '../constants';
|
|
11
12
|
const AddTeamMemberModal = ({ isOpen, onClose, }) => {
|
|
12
13
|
const intl = useIntl();
|
|
13
14
|
const { courseId = '' } = useParams();
|
|
@@ -30,7 +31,7 @@ const AddTeamMemberModal = ({ isOpen, onClose, }) => {
|
|
|
30
31
|
};
|
|
31
32
|
const handleSave = () => {
|
|
32
33
|
const identifiers = inputValue.split(',').map(user => user.trim()).filter(user => user);
|
|
33
|
-
addTeamMember({ identifiers, role: selectedRole }, {
|
|
34
|
+
addTeamMember({ identifiers, role: selectedRole, action: TEAM_MEMBER_ACTION.ALLOW }, {
|
|
34
35
|
onSuccess: (data) => {
|
|
35
36
|
var _a;
|
|
36
37
|
const failedUsernames = ((_a = data.results) === null || _a === void 0 ? void 0 : _a.filter(user => user.userDoesNotExist).map(user => user.identifier)) || [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AddTeamMemberModal.js","sourceRoot":"","sources":["../../../src/courseTeam/components/AddTeamMemberModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,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,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,QAAQ,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"AddTeamMemberModal.js","sourceRoot":"","sources":["../../../src/courseTeam/components/AddTeamMemberModal.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 { ActionRow, Button, Form, ModalDialog } from '@openedx/paragon';\nimport { useAddTeamMember, useRoles } from '@src/courseTeam/data/apiHook';\nimport messages from '@src/courseTeam/messages';\nimport { useCourseInfo } from '@src/data/apiHook';\nimport { useDebouncedFilter } from '@src/hooks/useDebouncedFilter';\nimport { useAlert } from '@src/providers/AlertProvider';\nimport { TEAM_MEMBER_ACTION } from '../constants';\n\ninterface AddTeamMemberModalProps {\n isOpen: boolean,\n onClose: () => void,\n}\n\nconst AddTeamMemberModal = ({\n isOpen,\n onClose,\n}: AddTeamMemberModalProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const { data: { displayName } = { displayName: '' } } = useCourseInfo(courseId);\n const { data: { results } = { results: [] } } = useRoles(courseId);\n const [users, setUsers] = useState('');\n const [selectedRole, setSelectedRole] = useState('');\n const { inputValue, handleChange } = useDebouncedFilter({\n filterValue: users,\n setFilter: setUsers,\n });\n const { mutate: addTeamMember } = useAddTeamMember(courseId);\n const { addAlert, showModal } = useAlert();\n\n const roles = [{ role: '', displayName: intl.formatMessage(messages.rolePlaceholder) }, ...(results || [])];\n\n const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n handleChange(e.target.value);\n };\n\n const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n setSelectedRole(e.target.value);\n };\n\n const handleSave = () => {\n const identifiers = inputValue.split(',').map(user => user.trim()).filter(user => user);\n addTeamMember({ identifiers, role: selectedRole, action: TEAM_MEMBER_ACTION.ALLOW }, {\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.failedToAddTeamMembers),\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 setUsers('');\n setSelectedRole('');\n onClose();\n },\n onError: () => {\n showModal({\n message: intl.formatMessage(messages.addTeamMemberError),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n };\n\n return (\n <ModalDialog isOpen={isOpen} onClose={onClose} title={intl.formatMessage(messages.addNewTeamMember)} isOverflowVisible={false} size=\"lg\">\n <ModalDialog.Header className=\"border-light-700 border-bottom\">\n <h3 className=\"text-primary-500\">{intl.formatMessage(messages.addNewTeamMember)}</h3>\n </ModalDialog.Header>\n <ModalDialog.Body className=\"position-relative overflow-auto\">\n <p>{intl.formatMessage(messages.addNewTeamMemberDescription, { courseName: displayName })}</p>\n <Form.Group>\n <Form.Label>{intl.formatMessage(messages.addUsersLabel)}</Form.Label>\n <Form.Control as=\"textarea\" rows={3} placeholder={intl.formatMessage(messages.usersPlaceholder)} value={inputValue} onChange={handleInputChange} />\n </Form.Group>\n <Form.Group>\n <Form.Label>{intl.formatMessage(messages.roleLabel)}</Form.Label>\n <Form.Control as=\"select\" defaultValue=\"\" disabled={roles.length === 1} onChange={handleSelectChange}>\n {\n roles.map((role) => (\n <option key={role.role} value={role.role}>\n {role.displayName}\n </option>\n ))\n }\n </Form.Control>\n </Form.Group>\n </ModalDialog.Body>\n <ModalDialog.Footer className=\"border-light-700 border-top\">\n <ActionRow>\n <Button variant=\"tertiary\" onClick={onClose}>{intl.formatMessage(messages.cancelButton)}</Button>\n <Button variant=\"primary\" onClick={handleSave} disabled={!selectedRole || !inputValue}>{intl.formatMessage(messages.saveButton)}</Button>\n </ActionRow>\n </ModalDialog.Footer>\n </ModalDialog>\n );\n};\n\nexport default AddTeamMemberModal;\n"]}
|
|
@@ -6,6 +6,7 @@ import { ActionRow, Button, Form, FormControl, FormLabel, ModalDialog } from '@o
|
|
|
6
6
|
import { useAddTeamMember, useRemoveTeamMember, useRoles } from '../../courseTeam/data/apiHook';
|
|
7
7
|
import messages from '../../courseTeam/messages';
|
|
8
8
|
import { useAlert } from '../../providers/AlertProvider';
|
|
9
|
+
import { TEAM_MEMBER_ACTION } from '../constants';
|
|
9
10
|
const EditTeamMemberModal = ({ isOpen, user, onClose }) => {
|
|
10
11
|
const intl = useIntl();
|
|
11
12
|
const { courseId = '' } = useParams();
|
|
@@ -41,7 +42,7 @@ const EditTeamMemberModal = ({ isOpen, user, onClose }) => {
|
|
|
41
42
|
onSuccess: () => {
|
|
42
43
|
// After successful removal, add new role if needed
|
|
43
44
|
if (hasRolesToAdd) {
|
|
44
|
-
addTeamMember({ identifiers: [user.username], role: selectedRole }, {
|
|
45
|
+
addTeamMember({ identifiers: [user.username], role: selectedRole, action: TEAM_MEMBER_ACTION.ALLOW }, {
|
|
45
46
|
onSuccess: () => {
|
|
46
47
|
onClose();
|
|
47
48
|
},
|
|
@@ -69,7 +70,7 @@ const EditTeamMemberModal = ({ isOpen, user, onClose }) => {
|
|
|
69
70
|
}
|
|
70
71
|
else if (hasRolesToAdd) {
|
|
71
72
|
// Only add operation needed
|
|
72
|
-
addTeamMember({ identifiers: [user.username], role: selectedRole }, {
|
|
73
|
+
addTeamMember({ identifiers: [user.username], role: selectedRole, action: TEAM_MEMBER_ACTION.ALLOW }, {
|
|
73
74
|
onSuccess: () => {
|
|
74
75
|
onClose();
|
|
75
76
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditTeamMemberModal.js","sourceRoot":"","sources":["../../../src/courseTeam/components/EditTeamMemberModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { ActionRow, Button, Form, FormControl, FormLabel, ModalDialog } from '@openedx/paragon';\nimport { useAddTeamMember, useRemoveTeamMember, useRoles } from '@src/courseTeam/data/apiHook';\nimport messages from '@src/courseTeam/messages';\nimport { CourseTeamMember, Role } from '@src/courseTeam/types';\nimport { useAlert } from '@src/providers/AlertProvider';\n\ninterface EditTeamMemberModalProps {\n isOpen: boolean,\n user: CourseTeamMember,\n onClose: () => void,\n}\n\nconst EditTeamMemberModal = ({ isOpen, user, onClose }: EditTeamMemberModalProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [selectedRole, setSelectedRole] = useState('');\n const [keepRoles, setKeepRoles] = useState<string[]>([]);\n const { mutate: addTeamMember, isPending: isAdding } = useAddTeamMember(courseId);\n const { mutate: removeTeamMember, isPending: isRemoving } = useRemoveTeamMember(courseId);\n const { showModal } = useAlert();\n\n const { data: { results } = { results: [] } } = useRoles(courseId);\n\n useEffect(() => {\n if (isOpen) {\n setKeepRoles(user.roles.map(role => role.role));\n setSelectedRole('');\n }\n }, [isOpen, user]);\n\n const filteredRoles = results?.filter(role => !user.roles.some(userRole => userRole.role === role.role)) || [];\n\n const roles = [{ role: '', displayName: intl.formatMessage(messages.rolePlaceholder) }, ...filteredRoles];\n\n const handleToggleRole = (roleName: string) => {\n if (keepRoles.includes(roleName)) {\n setKeepRoles(keepRoles.filter(role => role !== roleName));\n } else {\n setKeepRoles([...keepRoles, roleName]);\n }\n };\n\n const handleSave = () => {\n const rolesToRemove = user.roles.filter(role => !keepRoles.includes(role.role)).map(role => role.role);\n const hasRolesToAdd = selectedRole;\n const hasRolesToRemove = rolesToRemove.length > 0;\n\n // Sequential approach: remove roles first, then add new role\n if (hasRolesToRemove) {\n removeTeamMember({ identifier: user.username, roles: rolesToRemove }, {\n onSuccess: () => {\n // After successful removal, add new role if needed\n if (hasRolesToAdd) {\n addTeamMember({ identifiers: [user.username], role: selectedRole }, {\n onSuccess: () => {\n onClose();\n },\n onError: () => {\n showModal({\n message: intl.formatMessage(messages.addRoleError),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n } else {\n onClose();\n }\n },\n onError: () => {\n showModal({\n message: intl.formatMessage(messages.removeTeamMemberError, { username: user.username }),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n } else if (hasRolesToAdd) {\n // Only add operation needed\n addTeamMember({ identifiers: [user.username], role: selectedRole }, {\n onSuccess: () => {\n onClose();\n },\n onError: () => {\n showModal({\n message: intl.formatMessage(messages.addRoleError),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n }\n };\n\n return (\n <ModalDialog\n isOpen={isOpen}\n title={intl.formatMessage(messages.editTeamTitle, { username: user.username })}\n onClose={onClose}\n isOverflowVisible={false}\n >\n <ModalDialog.Header className=\"border-light-700 border-bottom\">\n <h3 className=\"text-primary-500\">{intl.formatMessage(messages.editTeamTitle, { username: user.username })}</h3>\n </ModalDialog.Header>\n <ModalDialog.Body className=\"position-relative overflow-auto\">\n <p>{intl.formatMessage(messages.editInstructions, { username: user.username })}</p>\n <Form.CheckboxSet onChange={(e: React.ChangeEvent<HTMLInputElement>) => handleToggleRole(e.target.value)} value={keepRoles} name=\"keepRoles\">\n {\n (user.roles || [])\n .map((role: Role) => (\n <Form.Checkbox className=\"mt-2\" key={role.role} value={role.role}>\n {role.displayName}\n </Form.Checkbox>\n ))\n }\n </Form.CheckboxSet>\n <FormLabel className=\"mt-4\">{intl.formatMessage(messages.addRole)}</FormLabel>\n <FormControl\n as=\"select\"\n disabled={roles.length === 1}\n onChange={(e: React.ChangeEvent<HTMLSelectElement>) => setSelectedRole(e.target.value)}\n value={selectedRole}\n >\n {\n roles.map((role) => (\n <option key={role.role} value={role.role}>\n {role.displayName}\n </option>\n ))\n }\n </FormControl>\n </ModalDialog.Body>\n <ModalDialog.Footer className=\"border-light-700 border-top\">\n <ActionRow>\n <Button variant=\"tertiary\" onClick={onClose}>{intl.formatMessage(messages.cancelButton)}</Button>\n <Button variant=\"primary\" onClick={handleSave} disabled={isAdding || isRemoving || (keepRoles.length === user.roles.length && !selectedRole)}>\n {intl.formatMessage(messages.saveButton)}\n </Button>\n </ActionRow>\n </ModalDialog.Footer>\n </ModalDialog>\n );\n};\n\nexport default EditTeamMemberModal;\n"]}
|
|
1
|
+
{"version":3,"file":"EditTeamMemberModal.js","sourceRoot":"","sources":["../../../src/courseTeam/components/EditTeamMemberModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { ActionRow, Button, Form, FormControl, FormLabel, ModalDialog } from '@openedx/paragon';\nimport { useAddTeamMember, useRemoveTeamMember, useRoles } from '@src/courseTeam/data/apiHook';\nimport messages from '@src/courseTeam/messages';\nimport { CourseTeamMember, Role } from '@src/courseTeam/types';\nimport { useAlert } from '@src/providers/AlertProvider';\nimport { TEAM_MEMBER_ACTION } from '../constants';\n\ninterface EditTeamMemberModalProps {\n isOpen: boolean,\n user: CourseTeamMember,\n onClose: () => void,\n}\n\nconst EditTeamMemberModal = ({ isOpen, user, onClose }: EditTeamMemberModalProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [selectedRole, setSelectedRole] = useState('');\n const [keepRoles, setKeepRoles] = useState<string[]>([]);\n const { mutate: addTeamMember, isPending: isAdding } = useAddTeamMember(courseId);\n const { mutate: removeTeamMember, isPending: isRemoving } = useRemoveTeamMember(courseId);\n const { showModal } = useAlert();\n\n const { data: { results } = { results: [] } } = useRoles(courseId);\n\n useEffect(() => {\n if (isOpen) {\n setKeepRoles(user.roles.map(role => role.role));\n setSelectedRole('');\n }\n }, [isOpen, user]);\n\n const filteredRoles = results?.filter(role => !user.roles.some(userRole => userRole.role === role.role)) || [];\n\n const roles = [{ role: '', displayName: intl.formatMessage(messages.rolePlaceholder) }, ...filteredRoles];\n\n const handleToggleRole = (roleName: string) => {\n if (keepRoles.includes(roleName)) {\n setKeepRoles(keepRoles.filter(role => role !== roleName));\n } else {\n setKeepRoles([...keepRoles, roleName]);\n }\n };\n\n const handleSave = () => {\n const rolesToRemove = user.roles.filter(role => !keepRoles.includes(role.role)).map(role => role.role);\n const hasRolesToAdd = selectedRole;\n const hasRolesToRemove = rolesToRemove.length > 0;\n\n // Sequential approach: remove roles first, then add new role\n if (hasRolesToRemove) {\n removeTeamMember({ identifier: user.username, roles: rolesToRemove }, {\n onSuccess: () => {\n // After successful removal, add new role if needed\n if (hasRolesToAdd) {\n addTeamMember({ identifiers: [user.username], role: selectedRole, action: TEAM_MEMBER_ACTION.ALLOW }, {\n onSuccess: () => {\n onClose();\n },\n onError: () => {\n showModal({\n message: intl.formatMessage(messages.addRoleError),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n } else {\n onClose();\n }\n },\n onError: () => {\n showModal({\n message: intl.formatMessage(messages.removeTeamMemberError, { username: user.username }),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n } else if (hasRolesToAdd) {\n // Only add operation needed\n addTeamMember({ identifiers: [user.username], role: selectedRole, action: TEAM_MEMBER_ACTION.ALLOW }, {\n onSuccess: () => {\n onClose();\n },\n onError: () => {\n showModal({\n message: intl.formatMessage(messages.addRoleError),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n }\n };\n\n return (\n <ModalDialog\n isOpen={isOpen}\n title={intl.formatMessage(messages.editTeamTitle, { username: user.username })}\n onClose={onClose}\n isOverflowVisible={false}\n >\n <ModalDialog.Header className=\"border-light-700 border-bottom\">\n <h3 className=\"text-primary-500\">{intl.formatMessage(messages.editTeamTitle, { username: user.username })}</h3>\n </ModalDialog.Header>\n <ModalDialog.Body className=\"position-relative overflow-auto\">\n <p>{intl.formatMessage(messages.editInstructions, { username: user.username })}</p>\n <Form.CheckboxSet onChange={(e: React.ChangeEvent<HTMLInputElement>) => handleToggleRole(e.target.value)} value={keepRoles} name=\"keepRoles\">\n {\n (user.roles || [])\n .map((role: Role) => (\n <Form.Checkbox className=\"mt-2\" key={role.role} value={role.role}>\n {role.displayName}\n </Form.Checkbox>\n ))\n }\n </Form.CheckboxSet>\n <FormLabel className=\"mt-4\">{intl.formatMessage(messages.addRole)}</FormLabel>\n <FormControl\n as=\"select\"\n disabled={roles.length === 1}\n onChange={(e: React.ChangeEvent<HTMLSelectElement>) => setSelectedRole(e.target.value)}\n value={selectedRole}\n >\n {\n roles.map((role) => (\n <option key={role.role} value={role.role}>\n {role.displayName}\n </option>\n ))\n }\n </FormControl>\n </ModalDialog.Body>\n <ModalDialog.Footer className=\"border-light-700 border-top\">\n <ActionRow>\n <Button variant=\"tertiary\" onClick={onClose}>{intl.formatMessage(messages.cancelButton)}</Button>\n <Button variant=\"primary\" onClick={handleSave} disabled={isAdding || isRemoving || (keepRoles.length === user.roles.length && !selectedRole)}>\n {intl.formatMessage(messages.saveButton)}\n </Button>\n </ActionRow>\n </ModalDialog.Footer>\n </ModalDialog>\n );\n};\n\nexport default EditTeamMemberModal;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/courseTeam/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,KAAK,EAAE,OAAO;CACN,CAAC","sourcesContent":["export const TEAM_MEMBER_ACTION = {\n ALLOW: 'allow',\n} as const;\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DataList } from '../../types';
|
|
2
|
-
import { TeamMembersResponse, CourseTeamMember, CourseTeamMemberQueryParams, Role } from '../../courseTeam/types';
|
|
2
|
+
import { TeamMembersResponse, CourseTeamMember, CourseTeamMemberQueryParams, Role, AddTeamMemberParams } from '../../courseTeam/types';
|
|
3
3
|
export declare const getTeamMembers: (courseId: string, params: CourseTeamMemberQueryParams) => Promise<DataList<CourseTeamMember>>;
|
|
4
4
|
export declare const getRoles: (courseId: string) => Promise<Omit<DataList<Role>, "numPages" | "count">>;
|
|
5
|
-
export declare const addTeamMember: (courseId: string,
|
|
5
|
+
export declare const addTeamMember: (courseId: string, params: AddTeamMemberParams) => Promise<TeamMembersResponse>;
|
|
6
6
|
export declare const removeTeamMember: (courseId: string, identifier: string, roles: string[]) => Promise<TeamMembersResponse>;
|
|
@@ -27,8 +27,8 @@ export const getRoles = (courseId) => __awaiter(void 0, void 0, void 0, function
|
|
|
27
27
|
const { data } = yield getAuthenticatedHttpClient().get(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team/roles`);
|
|
28
28
|
return camelCaseObject(data);
|
|
29
29
|
});
|
|
30
|
-
export const addTeamMember = (courseId,
|
|
31
|
-
const { data } = yield getAuthenticatedHttpClient().post(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team`,
|
|
30
|
+
export const addTeamMember = (courseId, params) => __awaiter(void 0, void 0, void 0, function* () {
|
|
31
|
+
const { data } = yield getAuthenticatedHttpClient().post(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team`, params);
|
|
32
32
|
return camelCaseObject(data);
|
|
33
33
|
});
|
|
34
34
|
export const removeTeamMember = (courseId, identifier, roles) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/courseTeam/data/api.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/courseTeam/data/api.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAU9C,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,QAAgB,EAChB,MAAmC,EACE,EAAE;IACvC,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,mBAAmB,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CACrD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,SAAS,WAAW,CAAC,QAAQ,EAAE,EAAE,CAC1F,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAO,QAAgB,EAAuD,EAAE;IACtG,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CACrD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,aAAa,CACtE,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAO,QAAgB,EAAE,MAA2B,EAAgC,EAAE;IACjH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,IAAI,CACtD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,OAAO,EAC/D,MAAM,CACP,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAO,QAAgB,EAAE,UAAkB,EAAE,KAAe,EAAgC,EAAE;IAC5H,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,MAAM,CACxD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,SAAS,UAAU,EAAE,EAC7E,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,CACpB,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC","sourcesContent":["import { camelCaseObject, getAuthenticatedHttpClient } from '@openedx/frontend-base';\nimport { getApiBaseUrl } from '@src/data/api';\nimport { DataList } from '@src/types';\nimport {\n TeamMembersResponse,\n CourseTeamMember,\n CourseTeamMemberQueryParams,\n Role,\n AddTeamMemberParams,\n} from '@src/courseTeam/types';\n\nexport const getTeamMembers = async (\n courseId: string,\n params: CourseTeamMemberQueryParams\n): Promise<DataList<CourseTeamMember>> => {\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('email_or_username', params.emailOrUsername);\n }\n\n if (params.role) {\n queryParams.append('role', params.role);\n }\n\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team?${queryParams.toString()}`\n );\n return camelCaseObject(data);\n};\n\nexport const getRoles = async (courseId: string): Promise<Omit<DataList<Role>, 'numPages' | 'count'>> => {\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team/roles`\n );\n return camelCaseObject(data);\n};\n\nexport const addTeamMember = async (courseId: string, params: AddTeamMemberParams): Promise<TeamMembersResponse> => {\n const { data } = await getAuthenticatedHttpClient().post(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team`,\n params\n );\n return camelCaseObject(data);\n};\n\nexport const removeTeamMember = async (courseId: string, identifier: string, roles: string[]): Promise<TeamMembersResponse> => {\n const { data } = await getAuthenticatedHttpClient().delete(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team/${identifier}`,\n { data: { roles } }\n );\n return camelCaseObject(data);\n};\n"]}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import { CourseTeamMemberQueryParams } from '../../courseTeam/types';
|
|
1
|
+
import { AddTeamMemberParams, CourseTeamMemberQueryParams } from '../../courseTeam/types';
|
|
2
2
|
export declare const useTeamMembers: (courseId: string, params: CourseTeamMemberQueryParams) => import("@tanstack/react-query").UseQueryResult<import("../../types").DataList<import("../../courseTeam/types").CourseTeamMember>, Error>;
|
|
3
3
|
export declare const useRoles: (courseId: string) => import("@tanstack/react-query").UseQueryResult<Omit<import("../../types").DataList<import("../../courseTeam/types").Role>, "count" | "numPages">, Error>;
|
|
4
|
-
export declare const useAddTeamMember: (courseId: string) => import("@tanstack/react-query").UseMutationResult<import("../../courseTeam/types").TeamMembersResponse, Error,
|
|
5
|
-
identifiers: string[];
|
|
6
|
-
role: string;
|
|
7
|
-
}, unknown>;
|
|
4
|
+
export declare const useAddTeamMember: (courseId: string) => import("@tanstack/react-query").UseMutationResult<import("../../courseTeam/types").TeamMembersResponse, Error, AddTeamMemberParams, unknown>;
|
|
8
5
|
export declare const useRemoveTeamMember: (courseId: string) => import("@tanstack/react-query").UseMutationResult<import("../../courseTeam/types").TeamMembersResponse, Error, {
|
|
9
6
|
identifier: string;
|
|
10
7
|
roles: string[];
|
|
@@ -14,7 +14,7 @@ export const useRoles = (courseId) => (useQuery({
|
|
|
14
14
|
export const useAddTeamMember = (courseId) => {
|
|
15
15
|
const queryClient = useQueryClient();
|
|
16
16
|
return (useMutation({
|
|
17
|
-
mutationFn: (
|
|
17
|
+
mutationFn: (params) => addTeamMember(courseId, params),
|
|
18
18
|
onSuccess: () => {
|
|
19
19
|
queryClient.invalidateQueries({ queryKey: courseTeamQueryKeys.byCourse(courseId) });
|
|
20
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiHook.js","sourceRoot":"","sources":["../../../src/courseTeam/data/apiHook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAGrE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAE,MAAmC,EAAE,EAAE,CAAC,CACvF,QAAQ,CAAC;IACP,QAAQ,EAAE,mBAAmB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC;IACjE,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC/C,OAAO,EAAE,CAAC,CAAC,QAAQ;CACpB,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC,CAC5C,QAAQ,CAAC;IACP,QAAQ,EAAE,mBAAmB,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC7C,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACjC,OAAO,EAAE,CAAC,CAAC,QAAQ;CACpB,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAgB,EAAE,EAAE;IACnD,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,CAAC,WAAW,CAAC;QAClB,UAAU,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"apiHook.js","sourceRoot":"","sources":["../../../src/courseTeam/data/apiHook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAGrE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAE,MAAmC,EAAE,EAAE,CAAC,CACvF,QAAQ,CAAC;IACP,QAAQ,EAAE,mBAAmB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC;IACjE,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC/C,OAAO,EAAE,CAAC,CAAC,QAAQ;CACpB,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC,CAC5C,QAAQ,CAAC;IACP,QAAQ,EAAE,mBAAmB,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC7C,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACjC,OAAO,EAAE,CAAC,CAAC,QAAQ;CACpB,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAgB,EAAE,EAAE;IACnD,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,CAAC,WAAW,CAAC;QAClB,UAAU,EAAE,CAAC,MAA2B,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC5E,SAAS,EAAE,GAAG,EAAE;YACd,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACtF,CAAC;KACF,CAAC,CACD,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,QAAgB,EAAE,EAAE;IACtD,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,CAAC,WAAW,CAAC;QAClB,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,KAAK,EAA2C,EAAE,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC;QAC7H,SAAS,EAAE,GAAG,EAAE;YACd,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACtF,CAAC;KACF,CAAC,CACD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { addTeamMember, getRoles, getTeamMembers, removeTeamMember } from '@src/courseTeam/data/api';\nimport { courseTeamQueryKeys } from '@src/courseTeam/data/queryKeys';\nimport { AddTeamMemberParams, CourseTeamMemberQueryParams } from '@src/courseTeam/types';\n\nexport const useTeamMembers = (courseId: string, params: CourseTeamMemberQueryParams) => (\n useQuery({\n queryKey: courseTeamQueryKeys.byCoursePaginated(courseId, params),\n queryFn: () => getTeamMembers(courseId, params),\n enabled: !!courseId,\n })\n);\n\nexport const useRoles = (courseId: string) => (\n useQuery({\n queryKey: courseTeamQueryKeys.roles(courseId),\n queryFn: () => getRoles(courseId),\n enabled: !!courseId,\n })\n);\n\nexport const useAddTeamMember = (courseId: string) => {\n const queryClient = useQueryClient();\n return (useMutation({\n mutationFn: (params: AddTeamMemberParams) => addTeamMember(courseId, params),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: courseTeamQueryKeys.byCourse(courseId) });\n }\n })\n );\n};\n\nexport const useRemoveTeamMember = (courseId: string) => {\n const queryClient = useQueryClient();\n return (useMutation({\n mutationFn: ({ identifier, roles }: { identifier: string, roles: string[] }) => removeTeamMember(courseId, identifier, roles),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: courseTeamQueryKeys.byCourse(courseId) });\n }\n })\n );\n};\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TEAM_MEMBER_ACTION } from './constants';
|
|
1
2
|
export interface CourseTeamMember {
|
|
2
3
|
username: string;
|
|
3
4
|
fullName: string;
|
|
@@ -20,3 +21,9 @@ export interface TeamMembersResponse {
|
|
|
20
21
|
userDoesNotExist: boolean;
|
|
21
22
|
}[];
|
|
22
23
|
}
|
|
24
|
+
export type TeamMemberActionType = typeof TEAM_MEMBER_ACTION[keyof typeof TEAM_MEMBER_ACTION];
|
|
25
|
+
export interface AddTeamMemberParams {
|
|
26
|
+
identifiers: string[];
|
|
27
|
+
role: string;
|
|
28
|
+
action: TeamMemberActionType;
|
|
29
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/courseTeam/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/courseTeam/types.ts"],"names":[],"mappings":"AAOC,CAAC","sourcesContent":["import { TEAM_MEMBER_ACTION } from './constants';\n\nexport interface CourseTeamMember {\n username: string,\n fullName: string,\n email: string,\n roles: Role[],\n};\n\nexport interface CourseTeamMemberQueryParams {\n page: number,\n pageSize: number,\n emailOrUsername?: string,\n role?: string,\n}\n\nexport interface Role {\n role: string,\n displayName: string,\n}\n\nexport interface TeamMembersResponse {\n results: {\n identifier: string,\n userDoesNotExist: boolean,\n }[],\n}\n\nexport type TeamMemberActionType = typeof TEAM_MEMBER_ACTION[keyof typeof TEAM_MEMBER_ACTION];\n\nexport interface AddTeamMemberParams {\n identifiers: string[],\n role: string,\n action: TeamMemberActionType,\n}\n"]}
|
|
@@ -29,7 +29,7 @@ const AddExtensionModal = ({ isOpen, title, onClose, onSubmit }) => {
|
|
|
29
29
|
onSubmit({
|
|
30
30
|
emailOrUsername,
|
|
31
31
|
blockId,
|
|
32
|
-
dueDatetime: new Date(`${dueDate}T${dueTime}`).toISOString(),
|
|
32
|
+
dueDatetime: new Date(`${dueDate}T${dueTime}Z`).toISOString(),
|
|
33
33
|
reason
|
|
34
34
|
});
|
|
35
35
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AddExtensionModal.js","sourceRoot":"","sources":["../../../src/dateExtensions/components/AddExtensionModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3G,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,mBAAmB,MAAM,qCAAqC,CAAC;AACtE,OAAO,sBAAsB,MAAM,uDAAuD,CAAC;AAC3F,OAAO,QAAQ,MAAM,8BAA8B,CAAC;AAUpD,MAAM,eAAe,GAA6B;IAChD,eAAe,EAAE,EAAE;IACnB,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,OAAO;IAChB,MAAM,EAAE,EAAE;CACX,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAA0B,EAAE,EAAE;IACzF,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAC;IAE1D,MAAM,YAAY,GAAG,CAAC,QAAkC,EAAE,EAAE;QAC1D,OAAO,CACL,QAAQ,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE;eACnC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE;eAC9B,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,CAClC,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,GAAG,EAAE;QACrB,WAAW,CAAC,eAAe,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,CAAC,KAAuC,EAAE,EAAE;QAC/D,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;QACxE,QAAQ,CAAC;YACP,eAAe;YACf,OAAO;YACP,WAAW,EAAE,IAAI,IAAI,CAAC,GAAG,OAAO,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"AddExtensionModal.js","sourceRoot":"","sources":["../../../src/dateExtensions/components/AddExtensionModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from 'react';\nimport { ActionRow, Button, Form, FormControl, FormGroup, FormLabel, ModalDialog } from '@openedx/paragon';\nimport { useIntl } from '@openedx/frontend-base';\nimport SpecifyLearnerField from '@src/components/SpecifyLearnerField';\nimport SelectGradedSubsection from '@src/dateExtensions/components/SelectGradedSubsection';\nimport messages from '@src/dateExtensions/messages';\nimport { AddDateExtensionFormData, AddDateExtensionParams } from '@src/dateExtensions/types';\n\ninterface AddExtensionModalProps {\n isOpen: boolean,\n title: string,\n onClose: () => void,\n onSubmit: ({ emailOrUsername, blockId, dueDatetime, reason }: AddDateExtensionParams) => void,\n}\n\nconst initialFormData: AddDateExtensionFormData = {\n emailOrUsername: '',\n blockId: '',\n dueDate: '',\n dueTime: '23:59',\n reason: '',\n};\n\nconst AddExtensionModal = ({ isOpen, title, onClose, onSubmit }: AddExtensionModalProps) => {\n const intl = useIntl();\n const [formData, setFormData] = useState(initialFormData);\n\n const isFormFilled = (formData: AddDateExtensionFormData) => {\n return (\n formData.emailOrUsername.trim() !== ''\n && formData.blockId.trim() !== ''\n && formData.dueDate.trim() !== ''\n );\n };\n\n const resetForm = () => {\n setFormData(initialFormData);\n };\n\n const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const { emailOrUsername, blockId, dueDate, dueTime, reason } = formData;\n onSubmit({\n emailOrUsername,\n blockId,\n dueDatetime: new Date(`${dueDate}T${dueTime}Z`).toISOString(),\n reason\n });\n };\n\n const handleCancel = () => {\n resetForm();\n onClose();\n };\n\n const onChange = (event: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {\n const { name, value } = event.target;\n setFormData((prevData) => ({\n ...prevData,\n [name]: value,\n }));\n };\n\n return (\n <ModalDialog isOpen={isOpen} onClose={onClose} title={title} isOverflowVisible={false} size=\"xl\">\n <ModalDialog.Header className=\"p-3 pl-4 border-bottom\">\n <ModalDialog.Title as=\"h3\" className=\"m-0\">\n {title}\n </ModalDialog.Title>\n </ModalDialog.Header>\n <Form onSubmit={handleSubmit} className=\"position-relative overflow-auto\">\n <ModalDialog.Body>\n <div className=\"pt-3\">\n <p>{intl.formatMessage(messages.extensionInstructions)}</p>\n <div className=\"container-fluid border-bottom mb-4.5 pb-3\">\n <div className=\"row\">\n <div className=\"col-sm-12 col-md-6\">\n <SpecifyLearnerField onClickSelect={(emailOrUsername) => setFormData((prevData) => ({ ...prevData, emailOrUsername }))} />\n </div>\n <div className=\"col-sm-12 col-md-4\">\n <SelectGradedSubsection\n label={intl.formatMessage(messages.selectGradedSubsection)}\n placeholder={intl.formatMessage(messages.selectGradedSubsection)}\n onChange={onChange}\n />\n </div>\n </div>\n </div>\n <div>\n <h4>{intl.formatMessage(messages.defineExtension)}</h4>\n <FormGroup size=\"sm\">\n <FormLabel>\n {intl.formatMessage(messages.extensionDate)}:\n </FormLabel>\n <div className=\"d-md-flex w-md-50 align-items-center\">\n <FormControl name=\"dueDate\" type=\"date\" size=\"md\" onChange={onChange} />\n <FormControl name=\"dueTime\" type=\"time\" size=\"md\" className=\"mt-sm-3 mt-md-0\" defaultValue={initialFormData.dueTime} onChange={onChange} />\n </div>\n </FormGroup>\n <FormGroup className=\"mt-3\" size=\"sm\">\n <FormLabel>\n {intl.formatMessage(messages.reasonForExtension)}:\n </FormLabel>\n <FormControl name=\"reason\" placeholder={intl.formatMessage(messages.reasonForExtension)} size=\"md\" onChange={onChange} />\n </FormGroup>\n </div>\n </div>\n </ModalDialog.Body>\n <ModalDialog.Footer className=\"p-4 border-top\">\n <ActionRow>\n <Button variant=\"tertiary\" onClick={handleCancel}>{intl.formatMessage(messages.cancel)}</Button>\n <Button type=\"submit\" disabled={!isFormFilled(formData)}>\n {intl.formatMessage(messages.addExtension)}\n </Button>\n </ActionRow>\n </ModalDialog.Footer>\n </Form>\n </ModalDialog>\n );\n};\n\nexport default AddExtensionModal;\n"]}
|
|
@@ -48,7 +48,7 @@ const DateExtensionsList = ({ onResetExtensions = () => { }, onClickAdd = () =>
|
|
|
48
48
|
{
|
|
49
49
|
accessor: 'extendedDueDate',
|
|
50
50
|
Header: intl.formatMessage(messages.extendedDueDate),
|
|
51
|
-
Cell: ({ value }) => (intl.formatDate(value, { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', timeZone: 'UTC' })),
|
|
51
|
+
Cell: ({ value }) => (`${intl.formatDate(value, { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', timeZone: 'UTC' })} UTC`),
|
|
52
52
|
disableFilters: true,
|
|
53
53
|
},
|
|
54
54
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateExtensionsList.js","sourceRoot":"","sources":["../../../src/dateExtensions/components/DateExtensionsList.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 } from '@openedx/paragon';\nimport messages from '../messages';\nimport { LearnerDateExtension } from '../types';\nimport { useDateExtensions } from '../data/apiHook';\nimport SelectGradedSubsection from './SelectGradedSubsection';\nimport { useDebouncedFilter } from '../../hooks/useDebouncedFilter';\nimport { DataTableFetchDataProps } from '@src/types';\nimport UsernameFilter from '@src/components/UsernameFilter';\n\nconst DATE_EXTENSIONS_PAGE_SIZE = 25;\n\nexport interface DateExtensionListProps {\n onResetExtensions?: (user: LearnerDateExtension) => void,\n onClickAdd?: () => void,\n}\n\nconst GradedSubsectionFilter = ({ column: { filterValue, setFilter } }: { column: { filterValue: string, setFilter: (value: string) => void } }) => {\n const intl = useIntl();\n const { inputValue, handleChange } = useDebouncedFilter({\n filterValue,\n setFilter,\n });\n\n const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n handleChange(e.target.value);\n };\n\n return (\n <SelectGradedSubsection\n placeholder={intl.formatMessage(messages.allGradedSubsections)}\n onChange={handleSelectChange}\n value={inputValue}\n />\n );\n};\n\nconst DateExtensionsList = ({\n onResetExtensions = () => {},\n onClickAdd = () => {},\n}: DateExtensionListProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [filters, setFilters] = useState<{ page: number, emailOrUsername: string, blockId: string }>({\n page: 0,\n emailOrUsername: '',\n blockId: '',\n });\n\n const { data = { count: 0, results: [], numPages: 0 }, isLoading } = useDateExtensions(courseId ?? '', {\n blockId: filters.blockId,\n emailOrUsername: filters.emailOrUsername,\n page: filters.page,\n pageSize: DATE_EXTENSIONS_PAGE_SIZE,\n });\n\n const tableColumns = [\n { accessor: 'username',\n Header: intl.formatMessage(messages.username),\n Filter: UsernameFilter,\n },\n { accessor: 'fullName', Header: intl.formatMessage(messages.fullname), disableFilters: true, },\n { accessor: 'email', Header: intl.formatMessage(messages.email), disableFilters: true, },\n { accessor: 'unitTitle',\n Header: intl.formatMessage(messages.gradedSubsection),\n Filter: GradedSubsectionFilter,\n },\n {\n accessor: 'extendedDueDate',\n Header: intl.formatMessage(messages.extendedDueDate),\n Cell: ({ value }: { value: string }) => (\n intl.formatDate(value, { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', timeZone: 'UTC' })\n ),\n disableFilters: true,\n },\n ];\n\n const additionalColumns = [{\n id: 'reset',\n Header: intl.formatMessage(messages.reset),\n Cell: ({ row }: { row: { original: LearnerDateExtension } }) => (\n <Button\n variant=\"link\"\n size=\"inline\"\n onClick={() => onResetExtensions(row.original)}\n >\n {intl.formatMessage(messages.resetExtensions)}\n </Button>\n )\n }];\n\n const handleFetchData = (data: DataTableFetchDataProps) => {\n const emailOrUsernameFilter = data.filters.find((filter) => filter.id === 'username');\n const newEmailOrUsername = emailOrUsernameFilter ? emailOrUsernameFilter.value : '';\n const blockIdFilter = data.filters.find((filter) => filter.id === 'unitTitle');\n const newBlockId = blockIdFilter ? blockIdFilter.value : '';\n\n const filterChanged = newEmailOrUsername !== filters.emailOrUsername || newBlockId !== filters.blockId;\n const pageChanged = data.pageIndex !== filters.page;\n\n // If filters changed, reset to page 0\n if (filterChanged) {\n setFilters({ page: 0, emailOrUsername: newEmailOrUsername, blockId: newBlockId });\n } else if (pageChanged) {\n // If only page changed (filters didn't change), update page\n setFilters({ page: data.pageIndex, emailOrUsername: newEmailOrUsername, blockId: newBlockId });\n }\n };\n\n return (\n <DataTable\n columns={tableColumns}\n additionalColumns={additionalColumns}\n data={data.results}\n fetchData={handleFetchData}\n state={{\n pageIndex: filters.page,\n pageSize: DATE_EXTENSIONS_PAGE_SIZE,\n filters: [\n {\n id: 'username',\n value: filters.emailOrUsername,\n },\n {\n id: 'unitTitle',\n value: filters.blockId,\n }\n ]\n }}\n isFilterable\n numBreakoutFilters={2}\n isLoading={isLoading}\n isPaginated\n itemCount={data.count}\n manualFilters\n manualPagination\n pageSize={DATE_EXTENSIONS_PAGE_SIZE}\n pageCount={data.numPages}\n FilterStatusComponent={DataTable.RowStatus}\n >\n <div className=\"d-flex justify-content-between align-items-start pt-1 mx-3 mb-3\">\n <DataTable.TableControlBar />\n <Button className=\"mt-2.5\" onClick={onClickAdd}>+ {intl.formatMessage(messages.addIndividualExtension)}</Button>\n </div>\n <DataTable.Table />\n <DataTable.EmptyTable content={intl.formatMessage(messages.noDateExtensions)} />\n <DataTable.TableFooter />\n </DataTable>\n );\n};\n\nexport default DateExtensionsList;\n"]}
|
|
1
|
+
{"version":3,"file":"DateExtensionsList.js","sourceRoot":"","sources":["../../../src/dateExtensions/components/DateExtensionsList.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 } from '@openedx/paragon';\nimport messages from '../messages';\nimport { LearnerDateExtension } from '../types';\nimport { useDateExtensions } from '../data/apiHook';\nimport SelectGradedSubsection from './SelectGradedSubsection';\nimport { useDebouncedFilter } from '../../hooks/useDebouncedFilter';\nimport { DataTableFetchDataProps } from '@src/types';\nimport UsernameFilter from '@src/components/UsernameFilter';\n\nconst DATE_EXTENSIONS_PAGE_SIZE = 25;\n\nexport interface DateExtensionListProps {\n onResetExtensions?: (user: LearnerDateExtension) => void,\n onClickAdd?: () => void,\n}\n\nconst GradedSubsectionFilter = ({ column: { filterValue, setFilter } }: { column: { filterValue: string, setFilter: (value: string) => void } }) => {\n const intl = useIntl();\n const { inputValue, handleChange } = useDebouncedFilter({\n filterValue,\n setFilter,\n });\n\n const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n handleChange(e.target.value);\n };\n\n return (\n <SelectGradedSubsection\n placeholder={intl.formatMessage(messages.allGradedSubsections)}\n onChange={handleSelectChange}\n value={inputValue}\n />\n );\n};\n\nconst DateExtensionsList = ({\n onResetExtensions = () => {},\n onClickAdd = () => {},\n}: DateExtensionListProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [filters, setFilters] = useState<{ page: number, emailOrUsername: string, blockId: string }>({\n page: 0,\n emailOrUsername: '',\n blockId: '',\n });\n\n const { data = { count: 0, results: [], numPages: 0 }, isLoading } = useDateExtensions(courseId ?? '', {\n blockId: filters.blockId,\n emailOrUsername: filters.emailOrUsername,\n page: filters.page,\n pageSize: DATE_EXTENSIONS_PAGE_SIZE,\n });\n\n const tableColumns = [\n { accessor: 'username',\n Header: intl.formatMessage(messages.username),\n Filter: UsernameFilter,\n },\n { accessor: 'fullName', Header: intl.formatMessage(messages.fullname), disableFilters: true, },\n { accessor: 'email', Header: intl.formatMessage(messages.email), disableFilters: true, },\n { accessor: 'unitTitle',\n Header: intl.formatMessage(messages.gradedSubsection),\n Filter: GradedSubsectionFilter,\n },\n {\n accessor: 'extendedDueDate',\n Header: intl.formatMessage(messages.extendedDueDate),\n Cell: ({ value }: { value: string }) => (\n `${intl.formatDate(value, { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', timeZone: 'UTC' })} UTC`\n ),\n disableFilters: true,\n },\n ];\n\n const additionalColumns = [{\n id: 'reset',\n Header: intl.formatMessage(messages.reset),\n Cell: ({ row }: { row: { original: LearnerDateExtension } }) => (\n <Button\n variant=\"link\"\n size=\"inline\"\n onClick={() => onResetExtensions(row.original)}\n >\n {intl.formatMessage(messages.resetExtensions)}\n </Button>\n )\n }];\n\n const handleFetchData = (data: DataTableFetchDataProps) => {\n const emailOrUsernameFilter = data.filters.find((filter) => filter.id === 'username');\n const newEmailOrUsername = emailOrUsernameFilter ? emailOrUsernameFilter.value : '';\n const blockIdFilter = data.filters.find((filter) => filter.id === 'unitTitle');\n const newBlockId = blockIdFilter ? blockIdFilter.value : '';\n\n const filterChanged = newEmailOrUsername !== filters.emailOrUsername || newBlockId !== filters.blockId;\n const pageChanged = data.pageIndex !== filters.page;\n\n // If filters changed, reset to page 0\n if (filterChanged) {\n setFilters({ page: 0, emailOrUsername: newEmailOrUsername, blockId: newBlockId });\n } else if (pageChanged) {\n // If only page changed (filters didn't change), update page\n setFilters({ page: data.pageIndex, emailOrUsername: newEmailOrUsername, blockId: newBlockId });\n }\n };\n\n return (\n <DataTable\n columns={tableColumns}\n additionalColumns={additionalColumns}\n data={data.results}\n fetchData={handleFetchData}\n state={{\n pageIndex: filters.page,\n pageSize: DATE_EXTENSIONS_PAGE_SIZE,\n filters: [\n {\n id: 'username',\n value: filters.emailOrUsername,\n },\n {\n id: 'unitTitle',\n value: filters.blockId,\n }\n ]\n }}\n isFilterable\n numBreakoutFilters={2}\n isLoading={isLoading}\n isPaginated\n itemCount={data.count}\n manualFilters\n manualPagination\n pageSize={DATE_EXTENSIONS_PAGE_SIZE}\n pageCount={data.numPages}\n FilterStatusComponent={DataTable.RowStatus}\n >\n <div className=\"d-flex justify-content-between align-items-start pt-1 mx-3 mb-3\">\n <DataTable.TableControlBar />\n <Button className=\"mt-2.5\" onClick={onClickAdd}>+ {intl.formatMessage(messages.addIndividualExtension)}</Button>\n </div>\n <DataTable.Table />\n <DataTable.EmptyTable content={intl.formatMessage(messages.noDateExtensions)} />\n <DataTable.TableFooter />\n </DataTable>\n );\n};\n\nexport default DateExtensionsList;\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.
|
|
3
|
+
"version": "1.0.0-alpha.23",
|
|
4
4
|
"description": "The Open edX Instructor Dashboard",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "make build",
|
|
33
|
+
"build:ci": "make build-ci",
|
|
33
34
|
"build:packages": "make build-packages",
|
|
34
35
|
"clean": "make clean",
|
|
35
36
|
"clean:packages": "make clean-packages",
|