Skip to content

Commit

Permalink
Merge branch 'master' into kiram15/ENT-9489
Browse files Browse the repository at this point in the history
  • Loading branch information
kiram15 committed Oct 15, 2024
2 parents 610ea61 + 57c70ff commit 491e9e7
Show file tree
Hide file tree
Showing 23 changed files with 1,523 additions and 230 deletions.
736 changes: 698 additions & 38 deletions src/components/Admin/__snapshots__/Admin.test.jsx.snap

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/components/Admin/tabs/DownloadCSVButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ const DownloadCsvButton = ({ data, testId, fetchData }) => {
};

const handleClick = async () => {
setButtonState('pending');
fetchData().then((response) => {
setButtonState('pending');
const blob = new Blob([response.data], {
type: 'text/csv',
});
Expand Down
8 changes: 8 additions & 0 deletions src/components/Admin/tabs/ModuleActivityReport.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ const ModuleActivityReport = ({ enterpriseId }) => {
}),
accessor: 'percentage_completed_activities',
},
{
Header: intl.formatMessage({
id: 'adminPortal.LPR.moduleActivityReport.table.header.extensionsRequested',
defaultMessage: 'Extension Requests',
description: 'Header for the extensions requested column in the module activity report table',
}),
accessor: 'extensions_requested',
},
{
Header: intl.formatMessage({
id: 'adminPortal.LPR.moduleActivityReport.table.header.hoursOnline',
Expand Down
6 changes: 5 additions & 1 deletion src/components/AdvanceAnalyticsV2/AnalyticsV2Page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const AnalyticsV2Page = ({ enterpriseId }) => {
id="advance.analytics.data.refresh.msg"
defaultMessage="Data updated on {date}"
description="Data refresh message"
values={{ date: data?.lastUpdatedAt || '' }}
values={{ date: data?.lastUpdatedAt || currentDate }}
/>
</span>
</div>
Expand All @@ -64,6 +64,7 @@ const AnalyticsV2Page = ({ enterpriseId }) => {
value={startDate || data?.minEnrollmentDate}
min={data?.minEnrollmentDate}
onChange={(e) => setStartDate(e.target.value)}
disabled={isFetching}
/>
</Form.Group>
</div>
Expand All @@ -81,6 +82,7 @@ const AnalyticsV2Page = ({ enterpriseId }) => {
value={endDate || currentDate}
max={currentDate}
onChange={(e) => setEndDate(e.target.value)}
disabled={isFetching}
/>
</Form.Group>
</div>
Expand All @@ -97,6 +99,7 @@ const AnalyticsV2Page = ({ enterpriseId }) => {
as="select"
value={granularity}
onChange={(e) => setGranularity(e.target.value)}
disabled={isFetching}
>
<option value={GRANULARITY.DAILY}>
{intl.formatMessage({
Expand Down Expand Up @@ -142,6 +145,7 @@ const AnalyticsV2Page = ({ enterpriseId }) => {
as="select"
value={calculation}
onChange={(e) => setCalculation(e.target.value)}
disabled={isFetching}
>
<option value={CALCULATION.TOTAL}>
{intl.formatMessage({
Expand Down
132 changes: 132 additions & 0 deletions src/components/PeopleManagement/CreateGroupModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import React, { useCallback, useState, useEffect } from 'react';
import { logError } from '@edx/frontend-platform/logging';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { useIntl } from '@edx/frontend-platform/i18n';
import { snakeCaseObject } from '@edx/frontend-platform/utils';
import {
ActionRow, Button, FullscreenModal, StatefulButton, useToggle,
} from '@openedx/paragon';
import LmsApiService from '../../data/services/LmsApiService';
import InviteModalContent from '../learner-credit-management/invite-modal/InviteModalContent';
import SystemErrorAlertModal from '../learner-credit-management/cards/assignment-allocation-status-modals/SystemErrorAlertModal';

const CreateGroupModal = ({
isModalOpen,
closeModal,
enterpriseUUID,
}) => {
const intl = useIntl();
const [learnerEmails, setLearnerEmails] = useState([]);
const [createButtonState, setCreateButtonState] = useState('default');
const [groupName, setGroupName] = useState('');
const [canCreateGroup, setCanCreateGroup] = useState(false);
const [canInviteMembers, setCanInviteMembers] = useState(false);
const [isSystemErrorModalOpen, openSystemErrorModal, closeSystemErrorModal] = useToggle(false);
const handleCloseCreateGroupModal = () => {
closeModal();
setCreateButtonState('default');
};

const handleCreateGroup = async () => {
setCreateButtonState('pending');
const options = {
enterpriseUUID,
groupName,
};
let groupCreationResponse;

try {
groupCreationResponse = await LmsApiService.createEnterpriseGroup(options);
} catch (err) {
logError(err);
setCreateButtonState('error');
openSystemErrorModal();
}

try {
const requestBody = snakeCaseObject({
learnerEmails,
});
await LmsApiService.inviteEnterpriseLearnersToGroup(groupCreationResponse.data.uuid, requestBody);
setCreateButtonState('complete');
handleCloseCreateGroupModal();
} catch (err) {
logError(err);
setCreateButtonState('error');
openSystemErrorModal();
}
};

const handleEmailAddressesChange = useCallback((
value,
{ canInvite = false } = {},
) => {
setLearnerEmails(value);
setCanInviteMembers(canInvite);
}, []);

useEffect(() => {
setCanCreateGroup(false);
if (groupName.length > 0 && canInviteMembers) {
setCanCreateGroup(true);
}
}, [groupName, canInviteMembers]);

return (
<>
<FullscreenModal
className="stepper-modal bg-light-200"
isOpen={isModalOpen}
onClose={handleCloseCreateGroupModal}
title={intl.formatMessage({
id: 'peopleManagement.tab.create.group.modal.title',
defaultMessage: 'New group',
description: 'Title for creating a new group modal',
})}
footerNode={(
<ActionRow>
<ActionRow.Spacer />
<Button variant="tertiary" onClick={handleCloseCreateGroupModal}>Cancel</Button>
<StatefulButton
labels={{
default: 'Create',
pending: 'Creating...',
complete: 'Created',
error: 'Try again',
}}
variant="primary"
state={createButtonState}
disabled={!canCreateGroup}
onClick={handleCreateGroup}
/>
</ActionRow>
)}
>
<InviteModalContent
onSetGroupName={setGroupName}
onEmailAddressesChange={handleEmailAddressesChange}
isGroupInvite
/>
</FullscreenModal>
<SystemErrorAlertModal
isErrorModalOpen={isSystemErrorModalOpen}
closeErrorModal={closeSystemErrorModal}
closeAssignmentModal={handleCloseCreateGroupModal}
retry={handleCreateGroup}
/>
</>
);
};

const mapStateToProps = state => ({
enterpriseUUID: state.portalConfiguration.enterpriseId,
});

CreateGroupModal.propTypes = {
enterpriseUUID: PropTypes.string.isRequired,
isModalOpen: PropTypes.bool.isRequired,
closeModal: PropTypes.func.isRequired,
};

export default connect(mapStateToProps)(CreateGroupModal);
101 changes: 55 additions & 46 deletions src/components/PeopleManagement/DeleteGroupModal.jsx
Original file line number Diff line number Diff line change
@@ -1,68 +1,79 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useParams } from 'react-router-dom';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import { logError } from '@edx/frontend-platform/logging';
import {
ActionRow, Button, ModalDialog,
ActionRow, Button, ModalDialog, useToggle,
} from '@openedx/paragon';
import { RemoveCircleOutline } from '@openedx/paragon/icons';
import { logError } from '@edx/frontend-platform/logging';

import GeneralErrorModal from './GeneralErrorModal';
import { ROUTE_NAMES } from '../EnterpriseApp/data/constants';

import LmsApiService from '../../data/services/LmsApiService';

const DeleteGroupModal = ({
group, isOpen, close, setShowToast, setToastMessage,
group, isOpen, close,
}) => {
const { enterpriseSlug } = useParams();
const [isErrorOpen, openError, closeError] = useToggle(false);
const removeEnterpriseGroup = async () => {
try {
const response = await LmsApiService.removeEnterpriseGroup(group?.uuid);
if (response.status === 204) {
close();
setShowToast(true);
setToastMessage('Group deleted');
}
await LmsApiService.removeEnterpriseGroup(group?.uuid);
close();
// redirect back to the people management page
window.location.href = `/${enterpriseSlug}/admin/${ROUTE_NAMES.peopleManagement}`;
} catch (error) {
logError(error);
openError();
}
};
return (
<ModalDialog
title="Delete group"
isOpen={isOpen}
onClose={close}
hasCloseButton
isFullscreenOnMobile
>
<ModalDialog.Header>
<ModalDialog.Title>Delete group?</ModalDialog.Title>
</ModalDialog.Header>
<ModalDialog.Body>
<p className="pb-3">
<>
<GeneralErrorModal
isOpen={isErrorOpen}
close={closeError}
/>
<ModalDialog
title="Delete group"
isOpen={isOpen}
onClose={close}
hasCloseButton
isFullscreenOnMobile
>
<ModalDialog.Header>
<ModalDialog.Title>Delete group?</ModalDialog.Title>
</ModalDialog.Header>
<ModalDialog.Body>
<p className="pb-3">
<FormattedMessage
id="people.management.delete.group.modal.body.1"
defaultMessage="This action cannot be undone."
description="Warning shown when deleting a group."
/>
</p>
<FormattedMessage
id="people.management.delete.group.modal.body.1"
defaultMessage="This action cannot be undone."
description="Warning shown when deleting a group."
/>
</p>
<FormattedMessage
id="people.management.delete.group.modal.body.2"
defaultMessage={
id="people.management.delete.group.modal.body.2"
defaultMessage={
'By deleting this group you will no longer be able to track analytics associated'
+ 'with this group and the group will be removed from your People Management page.'
+ ' with this group and the group will be removed from your People Management page.'
}
description="Warning shown when deleting a group part 2."
/>
</ModalDialog.Body>
<ModalDialog.Footer>
<ActionRow>
<ModalDialog.CloseButton variant="tertiary">
Go back
</ModalDialog.CloseButton>
<Button variant="danger" data-testid="delete-group-button" onClick={removeEnterpriseGroup} iconBefore={RemoveCircleOutline}>
Delete group
</Button>
</ActionRow>
</ModalDialog.Footer>
</ModalDialog>
description="Warning shown when deleting a group part 2."
/>
</ModalDialog.Body>
<ModalDialog.Footer>
<ActionRow>
<ModalDialog.CloseButton variant="tertiary">
Go back
</ModalDialog.CloseButton>
<Button variant="danger" data-testid="delete-group-button" onClick={removeEnterpriseGroup} iconBefore={RemoveCircleOutline}>
Delete group
</Button>
</ActionRow>
</ModalDialog.Footer>
</ModalDialog>
</>
);
};

Expand All @@ -72,8 +83,6 @@ DeleteGroupModal.propTypes = {
}),
isOpen: PropTypes.bool.isRequired,
close: PropTypes.func.isRequired,
setShowToast: PropTypes.func.isRequired,
setToastMessage: PropTypes.func.isRequired,
};

export default DeleteGroupModal;
Loading

0 comments on commit 491e9e7

Please sign in to comment.