Skip to content

Commit

Permalink
Merge pull request #1260 from openedx/eahmadjaved/ENT-8873
Browse files Browse the repository at this point in the history
feat: mark static strings for i18n in members tab on budget detail page
  • Loading branch information
jajjibhai008 authored Jul 2, 2024
2 parents fbfdbab + 29be403 commit 3ab0a21
Show file tree
Hide file tree
Showing 10 changed files with 350 additions and 139 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Skeleton } from '@openedx/paragon';
import { FormattedMessage } from '@edx/frontend-platform/i18n';

import LearnerCreditGroupMembersTable from './LearnerCreditGroupMembersTable';
import {
Expand Down Expand Up @@ -39,9 +40,19 @@ const BudgetDetailMembersTabContents = ({ enterpriseUUID, refresh, setRefresh })
{!isRemovedMembersLoading ? (
<>
<div className="mb-4">
<h4 className="mt-1">Budget Members</h4>
<h4 className="mt-1">
<FormattedMessage
id="learnerCreditManagement.budgetDetail.membersTab.label"
defaultMessage="Budget Members"
description="Label for the Members tab in the Budget Detail page"
/>
</h4>
<p className="font-weight-light">
Members choose what to learn from the catalog and spend from the budget to enroll.
<FormattedMessage
id="learnerCreditManagement.budgetDetail.membersTab.description"
defaultMessage="Members choose what to learn from the catalog and spend from the budget to enroll."
description="Description for the Members tab in the Budget Detail page"
/>
</p>
</div>
<LearnerCreditGroupMembersTable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import { Download } from '@openedx/paragon/icons';
import { logError } from '@edx/frontend-platform/logging';
import snakeCase from 'lodash/snakeCase';
import { saveAs } from 'file-saver';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import EnterpriseAccessApiService from '../../../data/services/EnterpriseAccessApiService';
import { useBudgetId, useSubsidyAccessPolicy } from '../data';

const GroupMembersCsvDownloadTableAction = ({
isEntireTableSelected,
tableInstance,
}) => {
const intl = useIntl();
const selectedEmails = Object.keys(tableInstance.state.selectedRowIds);
const selectedEmailCount = selectedEmails.length;
const [alertModalOpen, setAlertModalOpen] = useState(false);
Expand Down Expand Up @@ -74,13 +76,21 @@ const GroupMembersCsvDownloadTableAction = ({
if (selectedEmailCount > 0) {
buttonSelectedNumber = isEntireTableSelected ? `(${tableInstance.itemCount})` : `(${selectedEmailCount})`;
} else {
buttonSelectedNumber = `all (${tableInstance.itemCount})`;
buttonSelectedNumber = intl.formatMessage({
id: 'learnerCreditManagement.budgetDetail.membersTab.membersTable.all',
defaultMessage: 'all ({itemCounts})',
description: 'All members selected in the Members table',
}, { itemCounts: tableInstance.itemCount });
}

return (
<>
<AlertModal
title="Something went wrong"
title={intl.formatMessage({
id: 'learnerCreditManagement.budgetDetail.membersTab.membersTable.error',
defaultMessage: 'Something went wrong',
description: 'Error title in the Members table',
})}
isOpen={alertModalOpen}
onClose={() => setAlertModalOpen(false)}
footerNode={(
Expand All @@ -89,14 +99,21 @@ const GroupMembersCsvDownloadTableAction = ({
variant="tertiary"
onClick={() => setAlertModalOpen(false)}
>
Close
<FormattedMessage
id="learnerCreditManagement.budgetDetail.membersTab.membersTable.close"
defaultMessage="Close"
description="Close button text in the Members table"
/>
</Button>
</ActionRow>
)}
>
<p>
We&apos;re sorry but something went wrong while downloading your CSV.
Please refer to the error below and try again later.
<FormattedMessage
id="learnerCreditManagement.budgetDetail.membersTab.membersTable.errorDownload"
defaultMessage="We're sorry but something went wrong while downloading your CSV. Please refer to the error below and try again later."
description="Error message when downloading CSV in the Members table"
/>
</p>
<p>{alertModalExc}</p>
</AlertModal>
Expand All @@ -107,7 +124,12 @@ const GroupMembersCsvDownloadTableAction = ({
className="border rounded-0 border-dark-500"
disabled={tableInstance.itemCount === 0}
>
Download {buttonSelectedNumber}
<FormattedMessage
id="learnerCreditManagement.budgetDetail.membersTab.membersTable.download"
defaultMessage="Download {buttonSelectedNumber}"
description="Download button text in the Members table"
values={{ buttonSelectedNumber }}
/>
</Button>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
DataTable, Dropdown, Icon, IconButton,
} from '@openedx/paragon';
import { MoreVert, RemoveCircle } from '@openedx/paragon/icons';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import TableTextFilter from '../TableTextFilter';
import CustomDataTableEmptyState from '../CustomDataTableEmptyState';
import MemberDetailsTableCell from './MemberDetailsTableCell';
Expand Down Expand Up @@ -41,7 +42,12 @@ const KabobMenu = ({
/>
<Dropdown.Menu>
<Dropdown.Item onClick={handleRemoveClick}>
<Icon src={RemoveCircle} className="mr-2 text-danger-500" />Remove member
<Icon src={RemoveCircle} className="mr-2 text-danger-500" />
<FormattedMessage
id="learnerCreditManagement.budgetDetail.membersTab.kabobMenu.removeMember"
defaultMessage="Remove member"
description="Remove member option in the kabob menu"
/>
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
Expand Down Expand Up @@ -74,87 +80,98 @@ const LearnerCreditGroupMembersTable = ({
setRefresh,
groupUuid,
removedGroupMembersCount,
}) => (
<DataTable
isSortable
manualSortBy
isSelectable
SelectionStatusComponent={DataTable.ControlledSelectionStatus}
manualSelectColumn={selectColumn}
isPaginated
manualPagination
isFilterable
manualFilters
isLoading={isLoading}
defaultColumnValues={{ Filter: TableTextFilter }}
FilterStatusComponent={FilterStatus}
numBreakoutFilters={2}
tableActions={[<GroupMembersCsvDownloadTableAction />]}
columns={[
{
Header: 'Member Details',
accessor: 'memberDetails',
Cell: MemberDetailsTableCell,
},
{
Header: MemberStatusTableColumnHeader,
accessor: 'status',
Cell: MemberStatusTableCell,
Filter: removedGroupMembersCount > 0 ? (
<MembersTableSwitchFilter removedGroupMembersCount={removedGroupMembersCount} />
) : <div />,
filter: 'status',
},
{
Header: 'Recent action',
accessor: 'recentAction',
Cell: ({ row }) => row.original.recentAction,
disableFilters: true,
},
{
Header: MemberEnrollmentsTableColumnHeader,
accessor: 'enrollmentCount',
Cell: ({ row }) => row.original.enrollmentCount,
disableFilters: true,
},
]}
initialTableOptions={{
getRowId: row => row?.memberDetails.userEmail,
autoResetPage: true,
}}
initialState={{
pageSize: MEMBERS_TABLE_PAGE_SIZE,
pageIndex: DEFAULT_PAGE,
sortBy: [
{ id: 'memberDetails', desc: true },
],
filters: [],
}}
bulkActions={[
<MemberRemoveAction
refresh={refresh}
setRefresh={setRefresh}
groupUuid={groupUuid}
/>,
<GroupMembersCsvDownloadTableAction />,
]}
additionalColumns={[
{
id: 'action',
Header: '',
// eslint-disable-next-line react/no-unstable-nested-components
Cell: (props) => (
<KabobMenu {...props} groupUuid={groupUuid} refresh={refresh} setRefresh={setRefresh} />
),
},
]}
fetchData={fetchTableData}
data={tableData.results}
itemCount={tableData.itemCount}
pageCount={tableData.pageCount}
EmptyTableComponent={CustomDataTableEmptyState}
/>
);
}) => {
const intl = useIntl();
return (
<DataTable
isSortable
manualSortBy
isSelectable
SelectionStatusComponent={DataTable.ControlledSelectionStatus}
manualSelectColumn={selectColumn}
isPaginated
manualPagination
isFilterable
manualFilters
isLoading={isLoading}
defaultColumnValues={{ Filter: TableTextFilter }}
FilterStatusComponent={FilterStatus}
numBreakoutFilters={2}
tableActions={[<GroupMembersCsvDownloadTableAction />]}
columns={[
{
Header: intl.formatMessage({
id: 'learnerCreditManagement.budgetDetail.membersTab.columns.memberDetails',
defaultMessage: 'Member Details',
description: 'Column header for the Member Details column in the Members tab of the Budget Detail page',
}),
accessor: 'memberDetails',
Cell: MemberDetailsTableCell,
},
{
Header: MemberStatusTableColumnHeader,
accessor: 'status',
Cell: MemberStatusTableCell,
Filter: removedGroupMembersCount > 0 ? (
<MembersTableSwitchFilter removedGroupMembersCount={removedGroupMembersCount} />
) : <div />,
filter: 'status',
},
{
Header: intl.formatMessage({
id: 'learnerCreditManagement.budgetDetail.membersTab.columns.recentAction',
defaultMessage: 'Recent action',
description: 'Column header for the Recent action column in the Members tab of the Budget Detail page',
}),
accessor: 'recentAction',
Cell: ({ row }) => row.original.recentAction,
disableFilters: true,
},
{
Header: MemberEnrollmentsTableColumnHeader,
accessor: 'enrollmentCount',
Cell: ({ row }) => row.original.enrollmentCount,
disableFilters: true,
},
]}
initialTableOptions={{
getRowId: row => row?.memberDetails.userEmail,
autoResetPage: true,
}}
initialState={{
pageSize: MEMBERS_TABLE_PAGE_SIZE,
pageIndex: DEFAULT_PAGE,
sortBy: [
{ id: 'memberDetails', desc: true },
],
filters: [],
}}
bulkActions={[
<MemberRemoveAction
refresh={refresh}
setRefresh={setRefresh}
groupUuid={groupUuid}
/>,
<GroupMembersCsvDownloadTableAction />,
]}
additionalColumns={[
{
id: 'action',
Header: '',
// eslint-disable-next-line react/no-unstable-nested-components
Cell: (props) => (
<KabobMenu {...props} groupUuid={groupUuid} refresh={refresh} setRefresh={setRefresh} />
),
},
]}
fetchData={fetchTableData}
data={tableData.results}
itemCount={tableData.itemCount}
pageCount={tableData.pageCount}
EmptyTableComponent={CustomDataTableEmptyState}
/>
);
};

KabobMenu.propTypes = {
row: PropTypes.shape({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
import {
Person,
} from '@openedx/paragon/icons';
import { FormattedMessage } from '@edx/frontend-platform/i18n';

const MemberDetailsTableCell = ({
row,
Expand All @@ -26,7 +27,11 @@ const MemberDetailsTableCell = ({
memberDetails = (
<div className="mb-n3">
<p className="text-danger-500 font-weight-bold text-uppercase x-small mb-0">
Former member
<FormattedMessage
id="learnerCreditManagement.budgetDetail.membersTab.membersTable.removed.FormerMember"
defaultMessage="Former member"
description="Status of the member invitation for a removed member"
/>
</p>
<p>{row.original.memberDetails.userEmail}</p>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,29 @@ import {
Icon,
} from '@openedx/paragon';
import { InfoOutline } from '@openedx/paragon/icons';
import { FormattedMessage } from '@edx/frontend-platform/i18n';

const MemberEnrollmentsTableColumnHeader = () => (
<Stack gap={1} direction="horizontal">
<span data-testid="members-table-enrollments-column-header">
Enrollments
<FormattedMessage
id="learnerCreditManagement.budgetDetail.membersTab.membersTable.enrollmentsColumn"
defaultMessage="Enrollments"
description="Enrollments column header in the Members table"
/>
</span>
<OverlayTrigger
key="enrollments-column-tooltip"
placement="top"
overlay={(
<Tooltip id="enrollments-column-tooltip">
<div>Total number of enrollment originated from the budget</div>
<div>
<FormattedMessage
id="learnerCreditManagement.budgetDetail.membersTab.membersTable.enrollmentsColumn.tooltip"
defaultMessage="Total number of enrollment originated from the budget"
description="Tooltip for the Enrollments column header in the Members table"
/>
</div>
</Tooltip>
)}
>
Expand Down
Loading

0 comments on commit 3ab0a21

Please sign in to comment.