Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import AddMembersModalSummary from './AddMembersModalSummary';
import InviteSummaryCount from '../../learner-credit-management/invite-modal/InviteSummaryCount';
import FileUpload from '../../learner-credit-management/invite-modal/FileUpload';
import { EMAIL_ADDRESSES_INPUT_VALUE_DEBOUNCE_DELAY, isInviteEmailAddressesInputValueValid } from '../../learner-credit-management/cards/data';
import EnterpriseCustomerUserDatatable from '../EnterpriseCustomerUserDatatable';
import EnterpriseCustomerUserDataTable from '../EnterpriseCustomerUserDataTable';
import { useEnterpriseLearners } from '../../learner-credit-management/data';

const AddMembersModalContent = ({
Expand Down Expand Up @@ -129,7 +129,7 @@ const AddMembersModalContent = ({
<hr className="my-4" />
</Col>
</Row>
<EnterpriseCustomerUserDatatable
<EnterpriseCustomerUserDataTable
onHandleAddMembersBulkAction={handleAddMembersBulkAction}
onHandleRemoveMembersBulkAction={handleRemoveMembersBulkAction}
learnerEmails={learnerEmails}
Expand Down
4 changes: 2 additions & 2 deletions src/components/PeopleManagement/CreateGroupModalContent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import InviteSummaryCount from '../learner-credit-management/invite-modal/Invite
import FileUpload from '../learner-credit-management/invite-modal/FileUpload';
import { EMAIL_ADDRESSES_INPUT_VALUE_DEBOUNCE_DELAY, isInviteEmailAddressesInputValueValid } from '../learner-credit-management/cards/data';
import { MAX_LENGTH_GROUP_NAME } from './constants';
import EnterpriseCustomerUserDatatable from './EnterpriseCustomerUserDatatable';
import EnterpriseCustomerUserDataTable from './EnterpriseCustomerUserDataTable';
import { useEnterpriseLearners } from '../learner-credit-management/data';

const CreateGroupModalContent = ({
Expand Down Expand Up @@ -147,7 +147,7 @@ const CreateGroupModalContent = ({
<hr className="my-4" />
</Col>
</Row>
<EnterpriseCustomerUserDatatable
<EnterpriseCustomerUserDataTable
onHandleAddMembersBulkAction={handleAddMembersBulkAction}
onHandleRemoveMembersBulkAction={handleRemoveMembersBulkAction}
learnerEmails={learnerEmails}
Expand Down
236 changes: 236 additions & 0 deletions src/components/PeopleManagement/EnterpriseCustomerUserDataTable.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import {
Button,

Check failure on line 4 in src/components/PeopleManagement/EnterpriseCustomerUserDataTable.jsx

View workflow job for this annotation

GitHub Actions / tests

'Button' is defined but never used
CheckboxControl, DataTable, DataTableContext, Icon, IconButtonWithTooltip, Table, TextFilter,

Check failure on line 5 in src/components/PeopleManagement/EnterpriseCustomerUserDataTable.jsx

View workflow job for this annotation

GitHub Actions / tests

'Table' is defined but never used
} from '@openedx/paragon';

import {
GROUP_MEMBERS_TABLE_DEFAULT_PAGE, GROUP_MEMBERS_TABLE_PAGE_SIZE,
} from './constants';
import MemberDetailsCell from './MemberDetailsCell';
import AddMembersBulkAction from './GroupDetailPage/AddMembersBulkAction';
import RemoveMembersBulkAction from './RemoveMembersBulkAction';
import MemberJoinedDateCell from './MemberJoinedDateCell';
import { useEnterpriseMembersTableData } from './data/hooks';
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';

Check failure on line 16 in src/components/PeopleManagement/EnterpriseCustomerUserDataTable.jsx

View workflow job for this annotation

GitHub Actions / tests

`react` import should occur before import of `./constants`

Check failure on line 16 in src/components/PeopleManagement/EnterpriseCustomerUserDataTable.jsx

View workflow job for this annotation

GitHub Actions / tests

Expected a line break after this opening brace

Check failure on line 16 in src/components/PeopleManagement/EnterpriseCustomerUserDataTable.jsx

View workflow job for this annotation

GitHub Actions / tests

Expected a line break before this closing brace
import classNames from 'classnames';

Check failure on line 17 in src/components/PeopleManagement/EnterpriseCustomerUserDataTable.jsx

View workflow job for this annotation

GitHub Actions / tests

`classnames` import should occur before import of `./constants`

Check failure on line 17 in src/components/PeopleManagement/EnterpriseCustomerUserDataTable.jsx

View workflow job for this annotation

GitHub Actions / tests

'classNames' is defined but never used
import { HelpOutline } from '@openedx/paragon/icons';

Check failure on line 18 in src/components/PeopleManagement/EnterpriseCustomerUserDataTable.jsx

View workflow job for this annotation

GitHub Actions / tests

`@openedx/paragon/icons` import should occur before import of `./constants`

export const BaseSelectWithContext = ({ row, enterpriseGroupLearners }) => {
const {
indeterminate,
checked,
...toggleRowSelectedProps
} = row.getToggleRowSelectedProps();
const isAddedMember = enterpriseGroupLearners.find(learner => learner.lmsUserId === Number(row.id));
return (
<div>
<CheckboxControl
{...toggleRowSelectedProps}
title="Toggle row selected"
checked={checked}
disabled={isAddedMember}
style={{ cursor: isAddedMember ? null : 'pointer' }}
/>
</div>
);
};
const FilterStatus = (rest) => <DataTable.FilterStatus showFilteredFields={false} {...rest} />;

const EnterpriseCustomerUserDataTableContext = createContext();

const useCheckboxControlProps = (props) => {
const updatedProps = useMemo(
() => {
const { indeterminate, ...rest } = props;
return { isIndeterminate: indeterminate, ...rest };
},
[props],
);
return updatedProps;
};

const addSelectedRowAction = (row, itemCount) => ({
type: 'ADD ROW',
row,
itemCount,
});

const deleteSelectedRowAction = (rowId) => ({
type: 'DELETE ROW',
rowId,
});

function getSelectedRowsFromGroupLearners(enterpriseGroupLearners) {

Check failure on line 65 in src/components/PeopleManagement/EnterpriseCustomerUserDataTable.jsx

View workflow job for this annotation

GitHub Actions / tests

'getSelectedRowsFromGroupLearners' is defined but never used
const selections = enterpriseGroupLearners.reduce((acc, learner) => {
acc[learner.lmsUserId] = true;
return acc;
}, {});
return selections;
}

const CustomSelectColumnCell = ({ row }) => {

Check failure on line 73 in src/components/PeopleManagement/EnterpriseCustomerUserDataTable.jsx

View workflow job for this annotation

GitHub Actions / tests

'row' is missing in props validation
const { enterpriseGroupLearners } = useContext(EnterpriseCustomerUserDataTableContext);
const [isAddedMember, setIsAddedMember] = useState(false);
const {
itemCount,
controlledTableSelections: [, dispatch],
} = useContext(DataTableContext);

const toggleSelected = useCallback(
() => {
if (row.isSelected) {
dispatch(deleteSelectedRowAction(row.id));
} else {
dispatch(addSelectedRowAction(row, itemCount));
}
},
[itemCount, row, dispatch],
);

useEffect(() => {
setIsAddedMember(!!enterpriseGroupLearners.find(learner => learner.lmsUserId === Number(row.id)));
}, [enterpriseGroupLearners, row.id]);

const checkboxControlProps = useCheckboxControlProps(
row.getToggleRowSelectedProps(),
);

if (isAddedMember) {
return (
<IconButtonWithTooltip
tooltipContent={<div>This learner is already a member of this group.</div>}
src={HelpOutline}
iconAs={Icon}
size="inline"
/>
);
}

return (
<div className="pgn__data-table__controlled-select">
<CheckboxControl
{...checkboxControlProps}
onChange={toggleSelected}
disabled={isAddedMember}
style={{ cursor: isAddedMember ? null : 'pointer' }}
/>
</div>
);
};

const EnterpriseCustomerUserDataTable = ({
enterpriseId,
learnerEmails,
onHandleAddMembersBulkAction,
onHandleRemoveMembersBulkAction,
enterpriseGroupLearners,
}) => {
const {
isLoading,
enterpriseMembersTableData,
fetchEnterpriseMembersTableData,
} = useEnterpriseMembersTableData({ enterpriseId });

const selectColumn = {
id: 'selection',
Header: DataTable.ControlledSelectHeader,
// Cell: DataTable.ControlledSelect,
Cell: CustomSelectColumnCell,
disableSortBy: true,
};

const contextValue = useMemo(() => ({
enterpriseGroupLearners,
}), [enterpriseGroupLearners]);

return (
<EnterpriseCustomerUserDataTableContext.Provider value={contextValue}>
<DataTable
bulkActions={[
<AddMembersBulkAction
onHandleAddMembersBulkAction={onHandleAddMembersBulkAction}
enterpriseId={enterpriseId}
enterpriseGroupLearners={enterpriseGroupLearners}
/>,
<RemoveMembersBulkAction
enterpriseId={enterpriseId}
learnerEmails={learnerEmails}
onHandleRemoveMembersBulkAction={onHandleRemoveMembersBulkAction}
/>,
]}
columns={[
{
Header: 'Member details',
accessor: 'name',
Cell: MemberDetailsCell,
},
{
Header: 'Joined organization',
accessor: 'joinedOrg',
Cell: MemberJoinedDateCell,
disableFilters: true,
},
]}
initialState={{
pageIndex: GROUP_MEMBERS_TABLE_DEFAULT_PAGE,
pageSize: GROUP_MEMBERS_TABLE_PAGE_SIZE,
sortBy: [
{ id: 'name', desc: true },
],
filters: [],
// selectedRowIds: getSelectedRowsFromGroupLearners(enterpriseGroupLearners),
}}
data={enterpriseMembersTableData.results}
defaultColumnValues={{ Filter: TextFilter }}
FilterStatusComponent={FilterStatus}
fetchData={fetchEnterpriseMembersTableData}
isFilterable
isLoading={isLoading}
isPaginated
isSelectable
itemCount={enterpriseMembersTableData.itemCount}
manualFilters
manualPagination
isSortable
manualSortBy
initialTableOptions={{
getRowId: row => row.enterpriseCustomerUser.userId.toString(),
}}
pageCount={enterpriseMembersTableData.pageCount}
manualSelectColumn={selectColumn}
SelectionStatusComponent={DataTable.ControlledSelectionStatus}
// onSelectedRowsChanged={(selectedRows) => {
// console.log('DEBUG?! onSelectedRowsChanged selectedRows', selectedRows);
// }}
/>
</EnterpriseCustomerUserDataTableContext.Provider>
);
};

EnterpriseCustomerUserDataTable.defaultProps = {
enterpriseGroupLearners: [],
};

EnterpriseCustomerUserDataTable.propTypes = {
enterpriseId: PropTypes.string.isRequired,
learnerEmails: PropTypes.arrayOf(PropTypes.string).isRequired,
onHandleRemoveMembersBulkAction: PropTypes.func.isRequired,
onHandleAddMembersBulkAction: PropTypes.func.isRequired,
enterpriseGroupLearners: PropTypes.arrayOf(PropTypes.shape({})),
};

BaseSelectWithContext.propTypes = {
row: PropTypes.shape({
getToggleRowSelectedProps: PropTypes.func.isRequired,
id: PropTypes.string,
}).isRequired,
enterpriseGroupLearners: PropTypes.arrayOf(PropTypes.shape({})),
};

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

export default connect(mapStateToProps)(EnterpriseCustomerUserDataTable);
Loading