Skip to content

Commit

Permalink
fix: adding group detail base page
Browse files Browse the repository at this point in the history
  • Loading branch information
kiram15 committed Oct 10, 2024
1 parent 25db621 commit 4ec4d2a
Show file tree
Hide file tree
Showing 13 changed files with 588 additions and 14 deletions.
15 changes: 12 additions & 3 deletions src/components/EnterpriseApp/EnterpriseAppRoutes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { EnterpriseSubsidiesContext } from '../EnterpriseSubsidiesContext';
import ContentHighlights from '../ContentHighlights';
import LearnerCreditManagementRoutes from '../learner-credit-management';
import PeopleManagementPage from '../PeopleManagement';
import GroupDetailPage from '../PeopleManagement/GroupDetailPage';

const EnterpriseAppRoutes = ({
email,
Expand Down Expand Up @@ -121,12 +122,20 @@ const EnterpriseAppRoutes = ({
/>
)}

{enterpriseGroupsV2 && enterpriseAppPage === ROUTE_NAMES.peopleManagement && (
{enterpriseGroupsV2 && enterpriseAppPage === ROUTE_NAMES.peopleManagement && ([
<Route
path="/:groupUuid"
key="group-detail"
element={(
<GroupDetailPage />
)}
/>,
<Route
path="/*"
key="people-management"
element={<PeopleManagementPage />}
/>
)}
/>,
])}

{enableContentHighlightsPage && enterpriseAppPage === ROUTE_NAMES.contentHighlights && (
<Route
Expand Down
1 change: 1 addition & 0 deletions src/components/EnterpriseApp/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ EnterpriseApp.propTypes = {
enableAnalyticsScreen: PropTypes.bool,
enableReportingConfigurationsScreen: PropTypes.bool,
enablePortalLearnerCreditManagementScreen: PropTypes.bool,
enterpriseGroupsV2: PropTypes.bool,
error: PropTypes.instanceOf(Error),
loading: PropTypes.bool,
};
Expand Down
85 changes: 85 additions & 0 deletions src/components/PeopleManagement/DeleteGroupModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useParams } from 'react-router-dom';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import {
ActionRow, Button, ModalDialog, useToggle,
} from '@openedx/paragon';
import { RemoveCircleOutline } from '@openedx/paragon/icons';
import GeneralErrorModal from './GeneralErrorModal';
import { ROUTE_NAMES } from '../EnterpriseApp/data/constants';

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

const DeleteGroupModal = ({
group, isOpen, close,
}) => {
const { enterpriseSlug } = useParams();
const [isErrorOpen, openError, closeError] = useToggle(false);
const removeEnterpriseGroup = async () => {
const response = await LmsApiService.removeEnterpriseGroup(group?.uuid);
if (response.status === 204) {
close();
// redirect back to the people management page
window.location.href = `/${enterpriseSlug}/admin/${ROUTE_NAMES.peopleManagement}`;
} else {
openError();
}
};
return (
<>
<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.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.'
}
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>
</>
);
};

DeleteGroupModal.propTypes = {
group: PropTypes.shape({
uuid: PropTypes.string.isRequired,
}),
isOpen: PropTypes.bool.isRequired,
close: PropTypes.func.isRequired,
};

export default DeleteGroupModal;
131 changes: 131 additions & 0 deletions src/components/PeopleManagement/EditGroupNameModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
ActionRow, Form, ModalDialog, Spinner, StatefulButton, useToggle,
} from '@openedx/paragon';

import MAX_LENGTH_GROUP_NAME from './constants';
import LmsApiService from '../../data/services/LmsApiService';
import GeneralErrorModal from './GeneralErrorModal';

const EditGroupNameModal = ({
group, isOpen, close, setShowToast, setToastMessage, forceUpdate,
}) => {
const intl = useIntl();
const [isErrorOpen, openError, closeError] = useToggle(false);
const [name, setName] = useState(group.name);
const [nameLength, setNameLength] = useState(group.name.length || 0);
const [buttonState, setButtonState] = useState('default');

const handleGroupNameChange = (e) => {
if (!e.target.value) {
setName('');
return;
}
if (e.target.value?.length > MAX_LENGTH_GROUP_NAME) {
return;
}
setNameLength(e.target.value?.length);
setName(e.target.value);
};

const editEnterpriseGroup = async () => {
setButtonState('pending');
try {
const formData = { name };
const response = await LmsApiService.updateEnterpriseGroup(group.uuid, formData);
if (response.status === 200) {
setButtonState('complete');
close();
setShowToast(true);
setToastMessage('Group name updated');
forceUpdate();
}
} catch (error) {
openError();
}
setButtonState('default');
};

return (
<>
<GeneralErrorModal isOpen={isErrorOpen} close={closeError} />
<ModalDialog
title="Edit group"
isOpen={isOpen}
onClose={close}
hasCloseButton
isFullscreenOnMobile
>
<ModalDialog.Header>
<ModalDialog.Title>Edit group name</ModalDialog.Title>
</ModalDialog.Header>
<ModalDialog.Body>
<Form.Control
value={name}
onChange={handleGroupNameChange}
label="name-your-group"
data-testid="group name input"
placeholder="Name"
/>
<Form.Control.Feedback>
{nameLength} / {MAX_LENGTH_GROUP_NAME}
</Form.Control.Feedback>
</ModalDialog.Body>

<ModalDialog.Footer>
<ActionRow>
<ModalDialog.CloseButton variant="tertiary">
Cancel
</ModalDialog.CloseButton>
<StatefulButton
state={buttonState}
labels={{
default: intl.formatMessage({
id: 'adminPortal.peopleManagement.editGroupNameModal.button.save',
defaultMessage: 'Save',
description:
'Label for the download button in the module activity report page.',
}),
pending: intl.formatMessage({
id: 'adminPortal.peopleManagement.editGroupNameModal.button.pending',
defaultMessage: 'Saving',
description:
'Label for the download button in the module activity report page when the download is in progress.',
}),
complete: intl.formatMessage({
id: 'adminPortal.peopleManagement.editGroupNameModal.button.complete',
defaultMessage: 'Saved',
description:
'Label for the download button in the module activity report page when the download is complete.',
}),
}}
icons={{
pending: (
<Spinner animation="border" variant="light" size="sm" />
),
}}
disabledStates={['pending']}
onClick={editEnterpriseGroup}
/>
</ActionRow>
</ModalDialog.Footer>
</ModalDialog>
</>
);
};

EditGroupNameModal.propTypes = {
group: PropTypes.shape({
uuid: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
}),
isOpen: PropTypes.bool.isRequired,
close: PropTypes.func.isRequired,
setShowToast: PropTypes.func.isRequired,
setToastMessage: PropTypes.func.isRequired,
forceUpdate: PropTypes.func.isRequired,
};

export default EditGroupNameModal;
46 changes: 46 additions & 0 deletions src/components/PeopleManagement/GeneralErrorModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import {
ActionRow, Button, ModalDialog,
} from '@openedx/paragon';

const GeneralErrorModal = ({ isOpen, close }) => (
<ModalDialog
title="Something went wrong"
isOpen={isOpen}
onClose={close}
hasCloseButton
isFullscreenOnMobile
>
<ModalDialog.Header>
<ModalDialog.Title>
<FormattedMessage
id="adminPortal.peopleManagement.errorModal.title"
defaultMessage="Something went wrong"
description="Title for error modal."
/>
</ModalDialog.Title>
</ModalDialog.Header>

<ModalDialog.Body>
<FormattedMessage
id="adminPortal.peopleManagement.errorModal.body"
defaultMessage="We're sorry. Something went wrong behind the scenes. Please try again, or reach out to customer support for help."
description="Message for error modal."
/>
</ModalDialog.Body>

<ModalDialog.Footer>
<ActionRow>
<Button onClick={close} variant="primary">Exit</Button>
</ActionRow>
</ModalDialog.Footer>
</ModalDialog>
);

GeneralErrorModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
close: PropTypes.func.isRequired,
};

export default GeneralErrorModal;
Loading

0 comments on commit 4ec4d2a

Please sign in to comment.