Skip to content

Commit

Permalink
feat: add user table with filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
katrinan029 committed Sep 5, 2024
1 parent 1fca718 commit 5456ed3
Show file tree
Hide file tree
Showing 9 changed files with 287 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import {
import { Launch, ContentCopy } from '@openedx/paragon/icons';
import { getConfig } from '@edx/frontend-platform';
import { formatDate, useCopyToClipboard } from '../data/utils';
import DJANGO_ADMIN_BASE_URL from '../data/constants';
import CustomerDetailModal from './CustomerDetailModal';

const CustomerCard = ({ enterpriseCustomer }) => {
const { ADMIN_PORTAL_BASE_URL } = getConfig();
const { ADMIN_PORTAL_BASE_URL, DJANGO_ADMIN_LMS_BASE_URL } = getConfig();
const { showToast, copyToClipboard, setShowToast } = useCopyToClipboard();
const [isDetailsOpen, openDetails, closeDetails] = useToggle(false);

Expand All @@ -28,7 +27,7 @@ const CustomerCard = ({ enterpriseCustomer }) => {
<Button
className="text-dark-500"
as="a"
href={`${DJANGO_ADMIN_BASE_URL}/admin/enterprise/enterprisecustomer/${enterpriseCustomer.uuid}/change`}
href={`${DJANGO_ADMIN_LMS_BASE_URL}/admin/enterprise/enterprisecustomer/${enterpriseCustomer.uuid}/change`}
variant="inverse-primary"
target="_blank"
rel="noopener noreferrer"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ const CustomerIntegrations = ({
<div>
{(activeSSO || activeIntegrations || apiCredentialsEnabled) && (
<div>
<h2>Associated Integrations</h2>
<h2>Associated integrations</h2>
<hr />
{activeSSO && activeSSO.map((sso) => (
<CustomerViewCard
slug={slug}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const CustomerPlanContainer = ({ slug }) => {
Show inactive
</Form.Switch>
</div>
<hr />
{renderActivePoliciesCard}
{renderActiveSubscriptions}
{showInactive ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
Icon, IconButton, Stack, Chip
Icon, IconButton, Stack, Chip,
} from '@openedx/paragon';
import { Person, Check, Timelapse } from '@openedx/paragon/icons';

export const EnterpriseCustomerUserDetail = ({
row,
}) => {
let memberDetails;
let memberDetailIcon = (
const memberDetailIcon = (
<IconButton
isActive
invertColors
Expand All @@ -31,7 +31,6 @@ export const EnterpriseCustomerUserDetail = ({
</div>
);
} else {
console.log(row.original)
memberDetails = (
<p className="align-middle mb-0">
{row.original.pendingEnterpriseCustomerUser?.userEmail}
Expand All @@ -47,20 +46,29 @@ export const EnterpriseCustomerUserDetail = ({
};

export const AdministratorCell = ({ row }) => {
if (row.original?.pendingEnterpriseCustomerUser?.isPendingAdmin) {
return (
<Chip
iconBefore={Timelapse}
>
Pending
</Chip>
);
}
return (
<div>
{row.original?.roleAssignments?.includes("enterprise_admin") ? <Check /> : null}
{row.original?.roleAssignments?.includes('enterprise_admin') ? <Check data-testid="admin check" aria-label="admin check" /> : null}
</div>
)
}
);
};

export const LearnerCell = ({ row }) => {
if (!row.original?.pendingEnterpriseCustomerUser) {
if (!row.original?.pendingEnterpriseCustomerUser?.isPendingLearner) {
return (
<div>
{row.original?.roleAssignments?.includes("enterprise_learner") ? <Check /> : null}
{row.original?.roleAssignments?.includes('enterprise_learner') ? <Check data-testid="learner check" aria-label="learner check" /> : null}
</div>
)
);
}

return (
Expand All @@ -69,20 +77,43 @@ export const LearnerCell = ({ row }) => {
>
Pending
</Chip>
)
);
};


EnterpriseCustomerUserDetail.propTypes = {
row: PropTypes.shape({
original: PropTypes.shape({
memberDetails: PropTypes.shape({
userEmail: PropTypes.string.isRequired,
userName: PropTypes.string,
enterpriseCustomerUser: PropTypes.shape({
email: PropTypes.string.isRequired,
username: PropTypes.string,
}),
pendingEnterpriseCustomerUser: PropTypes.shape({
isPendingAdmin: PropTypes.bool,
userEmail: PropTypes.string,
}),
roleAssignments: PropTypes.arrayOf(PropTypes.string),
}).isRequired,
}).isRequired,
};

AdministratorCell.propTypes = {
row: PropTypes.shape({
original: PropTypes.shape({
pendingEnterpriseCustomerUser: PropTypes.shape({
isPendingAdmin: PropTypes.bool,
}),
roleAssignments: PropTypes.arrayOf(PropTypes.string),
}).isRequired,
}).isRequired,
};

LearnerCell.propTypes = {
row: PropTypes.shape({
original: PropTypes.shape({
pendingEnterpriseCustomerUser: PropTypes.shape({
isPendingLearner: PropTypes.bool,
}),
status: PropTypes.string,
recentAction: PropTypes.string.isRequired,
memberEnrollments: PropTypes.string,
roleAssignments: PropTypes.arrayOf(PropTypes.string),
}).isRequired,
}).isRequired,
};
Original file line number Diff line number Diff line change
@@ -1,64 +1,62 @@
import { useParams } from 'react-router-dom';
import { Container, DataTable, TextFilter } from '@openedx/paragon';
import { DataTable, TextFilter } from '@openedx/paragon';
import { EnterpriseCustomerUserDetail, LearnerCell, AdministratorCell } from './EnterpriseCustomerUserDetail';
import useEnterpriseUsersTableData from '../data/hooks/useCustomerUsersTableData';
import useCustomerUsersTableData from '../data/hooks/useCustomerUsersTableData';

const EnterpriseCustomerUsersTable = () => {
const { id } = useParams();
const {
isLoading,
enterpriseUsersTableData,
fetchEnterpriseUsersData,
} = useEnterpriseUsersTableData(id);
} = useCustomerUsersTableData(id);
return (
<Container>
<h2>Associated users ({ enterpriseUsersTableData.itemCount })</h2>
<div>
<h2>Associated users ({enterpriseUsersTableData.itemCount})</h2>
<hr />
<DataTable
isLoading={isLoading}
isExpandable
isSortable
manualSortBy
isPaginated
manualPagination
isFilterable
manualFilters
initialState={{
pageSize: 8,
pageIndex: 0,
sortBy: [],
filters: [],
}}
defaultColumnValues={{ Filter: TextFilter }}
fetchData={fetchEnterpriseUsersData}
data={enterpriseUsersTableData.results}
itemCount={enterpriseUsersTableData.itemCount}
pageCount={enterpriseUsersTableData.pageCount}
columns={[
{
id: 'userDetails',
Header: 'User details',
accessor: 'userDetails',
Cell: EnterpriseCustomerUserDetail,
},
{
id: 'administrator',
Header: 'Administrator',
accessor: 'administrator',
disableFilters: true,
Cell: AdministratorCell,
},
{
id: 'learner',
Header: 'Learner',
accessor: 'learner',
disableFilters: true,
Cell: LearnerCell,
},
]}
/>
</Container>
<DataTable
isLoading={isLoading}
isExpandable
isPaginated
manualPagination
isFilterable
manualFilters
initialState={{
pageSize: 8,
pageIndex: 0,
sortBy: [],
filters: [],
}}
defaultColumnValues={{ Filter: TextFilter }}
fetchData={fetchEnterpriseUsersData}
data={enterpriseUsersTableData.results}
itemCount={enterpriseUsersTableData.itemCount}
pageCount={enterpriseUsersTableData.pageCount}
columns={[
{
id: 'details',
Header: 'User details',
accessor: 'details',
Cell: EnterpriseCustomerUserDetail,
},
{
id: 'administrator',
Header: 'Administrator',
accessor: 'administrator',
disableFilters: true,
Cell: AdministratorCell,
},
{
id: 'learner',
Header: 'Learner',
accessor: 'learner',
disableFilters: true,
Cell: LearnerCell,
},
]}
/>
</div>
);
};

export default EnterpriseCustomerUsersTable;
export default EnterpriseCustomerUsersTable;
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('CustomerViewIntegrations', () => {
</IntlProvider>,
);
await waitFor(() => {
expect(screen.getByText('Associated Integrations')).toBeInTheDocument();
expect(screen.getByText('Associated integrations')).toBeInTheDocument();

expect(screen.getByText('SSO')).toBeInTheDocument();
expect(screen.getByText('Orange cats rule')).toBeInTheDocument();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/* eslint-disable react/prop-types */
import {
screen,
render,
} from '@testing-library/react';
import '@testing-library/jest-dom';
import {
EnterpriseCustomerUserDetail,
AdministratorCell,
LearnerCell,
} from '../EnterpriseCustomerUserDetail';

describe('EnterpriseCustomerUserDetail', () => {
it('renders enterprise customer detail', () => {
const enterpriseCustomerUser = {
original: {
enterpriseCustomerUser: {
username: 'ash ketchum',
email: 'ash@ketchum.org',
},
},
};
render(<EnterpriseCustomerUserDetail row={enterpriseCustomerUser} />);
expect(screen.getByText('ash ketchum')).toBeInTheDocument();
expect(screen.getByText('ash@ketchum.org')).toBeInTheDocument();
});

it('renders pending enterprise customer detail', () => {
const pendingEnterpriseCustomerUser = {
original: {
pendingEnterpriseCustomerUser: {
userEmail: 'pending@customer.org',
},
},
};
render(<EnterpriseCustomerUserDetail row={pendingEnterpriseCustomerUser} />);
expect(screen.getByText('pending@customer.org')).toBeInTheDocument();
});

it('renders AdministratorCell there is a pending admin', () => {
const pendingAdmin = {
original: {
pendingEnterpriseCustomerUser: {
isPendingAdmin: true,
},
roleAssignments: ['enterprise_learner'],
},
};
render(<AdministratorCell row={pendingAdmin} />);
expect(screen.getByText('Pending')).toBeInTheDocument();
});

it('renders AdministratorCell there is a registered admin', () => {
const adminRow = {
original: {
pendingEnterpriseCustomerUser: {
isPendingAdmin: false,
},
roleAssignments: ['enterprise_admin'],
},
};
render(<AdministratorCell row={adminRow} />);
expect(screen.queryByText('Pending')).not.toBeInTheDocument();
});

it('renders LearnerCell when there is a registered learner and not pending', () => {
const learnerRow = {
original: {
pendingEnterpriseCustomerUser: null,
enterpriseCustomerUser: {
username: 'ash ketchum',
email: 'ash@ketchum.org',
},
roleAssignments: ['enterprise_learner'],
},
};
render(<LearnerCell row={learnerRow} />);
expect(screen.queryByText('Pending')).not.toBeInTheDocument();
});

it('renders LearnerCell for pending user', () => {
const pendingLearnerRow = {
original: {
pendingEnterpriseCustomerUser: {
isPendingLearner: true,
userEmail: 'pending@customer.org',
},
enterpriseCustomerUser: null,
},
};
render(<LearnerCell row={pendingLearnerRow} />);
expect(screen.queryByText('Pending')).toBeInTheDocument();
});
});
Loading

0 comments on commit 5456ed3

Please sign in to comment.