Skip to content

Commit

Permalink
fix: handle loading state
Browse files Browse the repository at this point in the history
  • Loading branch information
CodyWMitchell committed Jan 9, 2025
1 parent dc5772f commit 311db88
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 33 deletions.
55 changes: 36 additions & 19 deletions src/smart-components/access-management/EditUserGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ContentHeader from '@patternfly/react-component-groups/dist/esm/ContentHeader';
import { PageSection, PageSectionVariants } from '@patternfly/react-core';
import { PageSection, PageSectionVariants, Spinner } from '@patternfly/react-core';
import React, { useEffect, useMemo } from 'react';
import { useIntl } from 'react-intl';
import Messages from '../../Messages';
Expand All @@ -21,12 +21,21 @@ export const EditUserGroup: React.FunctionComponent = () => {

const group = useSelector((state: RBACStore) => state.groupReducer?.selectedGroup);
const allGroups = useSelector((state: RBACStore) => state.groupReducer?.groups?.data || []);
const [isLoading, setIsLoading] = React.useState(true);
const [isTableLoading, setIsTableLoading] = React.useState(true);

useEffect(() => {
dispatch(fetchGroups({ limit: 1000, offset: 0, orderBy: 'name', usesMetaInURL: true }));
if (groupId) {
dispatch(fetchGroup(groupId));
}
const fetchData = async () => {
try {
await Promise.all([
dispatch(fetchGroups({ limit: 1000, offset: 0, orderBy: 'name', usesMetaInURL: true })),
groupId ? dispatch(fetchGroup(groupId)) : Promise.resolve(),
]);
} finally {
setIsLoading(false);
}
};
fetchData();
}, [dispatch, groupId]);

const schema = {
Expand Down Expand Up @@ -60,6 +69,8 @@ export const EditUserGroup: React.FunctionComponent = () => {
{
name: 'users-and-service-accounts',
component: 'users-and-service-accounts',
initializeOnMount: true,
setTableLoaded: (value: boolean) => setIsTableLoading(value),
groupId: groupId,
},
],
Expand Down Expand Up @@ -116,20 +127,26 @@ export const EditUserGroup: React.FunctionComponent = () => {
<React.Fragment>
<ContentHeader title={intl.formatMessage(Messages.usersAndUserGroupsEditUserGroup)} subtitle={''} />
<PageSection data-ouia-component-id="edit-user-group-form" className="pf-v5-u-m-lg-on-lg" variant={PageSectionVariants.light} isWidthLimited>
<FormRenderer
schema={schema}
componentMapper={{
...componentMapper,
'users-and-service-accounts': EditGroupUsersAndServiceAccounts,
}}
onSubmit={handleSubmit}
onCancel={returnToPreviousPage}
FormTemplate={FormTemplate}
initialValues={initialValues}
FormTemplateProps={{
disableSubmit: ['pristine', 'invalid'],
}}
/>
{isLoading ? (
<div style={{ textAlign: 'center' }}>
<Spinner />
</div>
) : (
<FormRenderer
schema={schema}
componentMapper={{
...componentMapper,
'users-and-service-accounts': EditGroupUsersAndServiceAccounts,
}}
onSubmit={handleSubmit}
onCancel={returnToPreviousPage}
FormTemplate={FormTemplate}
FormTemplateProps={{
initialValues,
disableSubmit: ['pristine', 'invalid'],
}}
/>
)}
</PageSection>
</React.Fragment>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Pagination } from '@patternfly/react-core';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import { DataView, DataViewTable, DataViewToolbar, useDataViewPagination, useDataViewSelection } from '@patternfly/react-data-view';
import { EmptyState, EmptyStateBody, EmptyStateHeader, EmptyStateIcon, Pagination } from '@patternfly/react-core';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { DataView, DataViewState, DataViewTable, DataViewToolbar, useDataViewPagination, useDataViewSelection } from '@patternfly/react-data-view';
import { useDispatch, useSelector } from 'react-redux';
import { fetchServiceAccountsForGroup } from '../../redux/actions/group-actions';
import { RBACStore } from '../../redux/store';
Expand All @@ -9,9 +9,28 @@ import { fetchServiceAccounts } from '../../redux/actions/service-account-action
import useChrome from '@redhat-cloud-services/frontend-components/useChrome';
import { ServiceAccountsState } from '../../redux/reducers/service-account-reducer';
import { LAST_PAGE, ServiceAccount } from '../../helpers/service-account/service-account-helper';
import { BulkSelect, BulkSelectValue } from '@patternfly/react-component-groups';
import { BulkSelect, BulkSelectValue, SkeletonTableBody, SkeletonTableHead } from '@patternfly/react-component-groups';
import DateFormat from '@redhat-cloud-services/frontend-components/DateFormat';
import { Diff } from './EditUserGroupUsersAndServiceAccounts';
import Messages from '../../Messages';
import { FormattedMessage, useIntl } from 'react-intl';
import { SearchIcon } from '@patternfly/react-icons';

const EmptyTable: React.FunctionComponent<{ titleText: string }> = ({ titleText }) => {
return (
<EmptyState>
<EmptyStateHeader titleText={titleText} headingLevel="h4" icon={<EmptyStateIcon icon={SearchIcon} />} />
<EmptyStateBody>
<FormattedMessage
{...Messages['usersEmptyStateSubtitle']}
values={{
br: <br />,
}}
/>
</EmptyStateBody>
</EmptyState>
);
};

interface EditGroupServiceAccountsTableProps {
groupId?: string;
Expand Down Expand Up @@ -40,6 +59,19 @@ const EditGroupServiceAccountsTable: React.FunctionComponent<EditGroupServiceAcc
const { page, perPage, onSetPage, onPerPageSelect } = pagination;
const { auth, getEnvironmentDetails } = useChrome();
const initialServiceAccountIds = useRef<string[]>([]);
const [activeState, setActiveState] = useState<DataViewState | undefined>(DataViewState.loading);
const intl = useIntl();

const columns = useMemo(
() => [
intl.formatMessage(Messages.name),
intl.formatMessage(Messages.description),
intl.formatMessage(Messages.clientId),
intl.formatMessage(Messages.owner),
intl.formatMessage(Messages.timeCreated),
],
[intl]
);

const selection = useDataViewSelection({
matchOption: (a, b) => a.id === b.id,
Expand All @@ -53,13 +85,21 @@ const EditGroupServiceAccountsTable: React.FunctionComponent<EditGroupServiceAcc
};
}, []);

const { serviceAccounts, status } = useSelector(reducer);
const { serviceAccounts, status, isLoading } = useSelector(reducer);
const totalCount = useMemo(() => {
if (!serviceAccounts) return 0;
const currentCount = (page - 1) * perPage + serviceAccounts.length;
return status === LAST_PAGE ? currentCount : currentCount + 1;
}, [serviceAccounts, page, perPage, status]);

useEffect(() => {
if (isLoading) {
setActiveState(DataViewState.loading);
} else {
setActiveState(serviceAccounts.length === 0 ? DataViewState.empty : undefined);
}
}, [serviceAccounts.length, isLoading]);

const { groupServiceAccounts: groupServiceAccounts } = useSelector((state: RBACStore) => ({
groupServiceAccounts: state.groupReducer?.selectedGroup?.serviceAccounts?.data || [],
}));
Expand Down Expand Up @@ -169,7 +209,18 @@ const EditGroupServiceAccountsTable: React.FunctionComponent<EditGroupServiceAcc
/>
}
/>
<DataViewTable variant="compact" columns={['Name', 'Description', 'Client ID', 'Owner', 'Time created']} rows={rows} />
<DataViewTable
variant="compact"
columns={columns}
rows={rows}
headStates={{
loading: <SkeletonTableHead columns={columns} />,
}}
bodyStates={{
loading: <SkeletonTableBody rowsCount={10} columnsCount={columns.length} />,
empty: <EmptyTable titleText={intl.formatMessage(Messages.usersEmptyStateTitle)} />,
}}
/>
</DataView>
);
};
Expand Down
54 changes: 46 additions & 8 deletions src/smart-components/access-management/EditUserGroupUsers.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
import { Pagination } from '@patternfly/react-core';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import { DataView, DataViewTable, DataViewToolbar, useDataViewPagination, useDataViewSelection } from '@patternfly/react-data-view';
import { EmptyState, EmptyStateBody, EmptyStateHeader, EmptyStateIcon, Pagination } from '@patternfly/react-core';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { DataView, DataViewState, DataViewTable, DataViewToolbar, useDataViewPagination, useDataViewSelection } from '@patternfly/react-data-view';
import { useDispatch, useSelector } from 'react-redux';
import { RBACStore } from '../../redux/store';
import { fetchUsers } from '../../redux/actions/user-actions';
import { mappedProps } from '../../helpers/shared/helpers';
import { BulkSelect, BulkSelectValue } from '@patternfly/react-component-groups';
import { BulkSelect, BulkSelectValue, SkeletonTableBody, SkeletonTableHead } from '@patternfly/react-component-groups';
import { Diff } from './EditUserGroupUsersAndServiceAccounts';
import { useIntl } from 'react-intl';
import { FormattedMessage, useIntl } from 'react-intl';
import Messages from '../../Messages';
import { SearchIcon } from '@patternfly/react-icons';

const EmptyTable: React.FunctionComponent<{ titleText: string }> = ({ titleText }) => {
return (
<EmptyState>
<EmptyStateHeader titleText={titleText} headingLevel="h4" icon={<EmptyStateIcon icon={SearchIcon} />} />
<EmptyStateBody>
<FormattedMessage
{...Messages['usersEmptyStateSubtitle']}
values={{
br: <br />,
}}
/>
</EmptyStateBody>
</EmptyState>
);
};

interface EditGroupUsersTableUsersTableProps {
onChange: (userDiff: Diff) => void;
Expand All @@ -29,6 +46,7 @@ const EditGroupUsersTable: React.FunctionComponent<EditGroupUsersTableUsersTable
const { page, perPage, onSetPage, onPerPageSelect } = pagination;
const initialUserIds = useRef<string[]>([]);
const intl = useIntl();
const [activeState, setActiveState] = useState<DataViewState | undefined>(DataViewState.loading);

const columns = useMemo(
() => [
Expand All @@ -54,10 +72,11 @@ const EditGroupUsersTable: React.FunctionComponent<EditGroupUsersTableUsersTable
};
}, []);

const { users, groupUsers, totalCount } = useSelector((state: RBACStore) => ({
const { users, groupUsers, totalCount, isLoading } = useSelector((state: RBACStore) => ({
users: state.userReducer?.users?.data || [],
groupUsers: state.groupReducer?.selectedGroup?.members?.data || [],
totalCount: state.userReducer?.users?.meta?.count,
isLoading: state.userReducer?.isUserDataLoading,
}));

const rows = useMemo(
Expand All @@ -84,6 +103,14 @@ const EditGroupUsersTable: React.FunctionComponent<EditGroupUsersTableUsersTable
[dispatch]
);

useEffect(() => {
if (isLoading) {
setActiveState(DataViewState.loading);
} else {
setActiveState(users.length === 0 ? DataViewState.empty : undefined);
}
}, [users.length, isLoading]);

useEffect(() => {
fetchData({
limit: perPage,
Expand Down Expand Up @@ -121,7 +148,7 @@ const EditGroupUsersTable: React.FunctionComponent<EditGroupUsersTableUsersTable
};

return (
<DataView selection={{ ...selection }}>
<DataView selection={{ ...selection }} activeState={activeState}>
<DataViewToolbar
pagination={
<Pagination
Expand All @@ -145,7 +172,18 @@ const EditGroupUsersTable: React.FunctionComponent<EditGroupUsersTableUsersTable
/>
}
/>
<DataViewTable variant="compact" columns={columns} rows={rows} />
<DataViewTable
variant="compact"
columns={columns}
rows={rows}
headStates={{
loading: <SkeletonTableHead columns={columns} />,
}}
bodyStates={{
loading: <SkeletonTableBody rowsCount={10} columnsCount={columns.length} />,
empty: <EmptyTable titleText={intl.formatMessage(Messages.usersEmptyStateTitle)} />,
}}
/>
</DataView>
);
};
Expand Down

0 comments on commit 311db88

Please sign in to comment.