Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #35702 - Move Card Context to apply all host tabs #9494

Merged
merged 1 commit into from Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,80 @@
import PropTypes from 'prop-types';
import React, { useEffect, useReducer, useCallback } from 'react';

export const CardExpansionContext = React.createContext({});

const cardExpansionReducer = (state, action) => {
// A React reducer, not a Redux one!
switch (action.type) {
case 'expand':
return {
...state,
[action.key]: true,
};
case 'collapse':
return {
...state,
[action.key]: false,
};
case 'add':
if (state[action.key] === undefined) {
return {
...state,
[action.key]: true,
};
}
return state;
case 'expandAll': {
const expandedState = {};
Object.keys(state).forEach(key => {
expandedState[key] = true;
});
return expandedState;
}
case 'collapseAll': {
const collapsedState = {};
Object.keys(state).forEach(key => {
collapsedState[key] = false;
});
return collapsedState;
}
default:
throw new Error(`invalid card expansion type: ${action.type}`);
}
};

export const CardExpansionContextWrapper = ({ children }) => {
const [cardExpandStates, dispatch] = useReducer(cardExpansionReducer, {});
// On mount, get values from localStorage and set them in state
const initializeCardFromLocalStorage = useCallback(key => {
const value = localStorage.getItem(`${key} card expanded`);
if (value !== null && value !== undefined) {
dispatch({ type: value === 'true' ? 'expand' : 'collapse', key });
} else {
dispatch({ type: 'add', key });
}
}, []);
// On unmount, save the values to local storage
// eslint-disable-next-line arrow-body-style
useEffect(() => {
return () =>
Object.entries(cardExpandStates).forEach(([key, value]) =>
localStorage.setItem(`${key} card expanded`, value)
);
});
return (
<CardExpansionContext.Provider
value={{
cardExpandStates,
dispatch,
registerCard: initializeCardFromLocalStorage,
}}
>
{children}
</CardExpansionContext.Provider>
);
};

CardExpansionContextWrapper.propTypes = {
children: PropTypes.node.isRequired,
};
@@ -1,54 +1,13 @@
import PropTypes from 'prop-types';
import React, { useEffect, useReducer, useCallback } from 'react';
import React, { useEffect, useContext } from 'react';
import { Flex, FlexItem, Button } from '@patternfly/react-core';
import { registerCoreCards } from './CardRegistry';
import Slot from '../../../common/Slot';
import { STATUS } from '../../../../constants';
import '../Overview/styles.css';
import './styles.css';
import { translate as __ } from '../../../../common/I18n';

export const CardExpansionContext = React.createContext({});

const cardExpansionReducer = (state, action) => {
// A React reducer, not a Redux one!
switch (action.type) {
case 'expand':
return {
...state,
[action.key]: true,
};
case 'collapse':
return {
...state,
[action.key]: false,
};
case 'add':
if (state[action.key] === undefined) {
return {
...state,
[action.key]: true,
};
}
return state;
case 'expandAll': {
const expandedState = {};
Object.keys(state).forEach(key => {
expandedState[key] = true;
});
return expandedState;
}
case 'collapseAll': {
const collapsedState = {};
Object.keys(state).forEach(key => {
collapsedState[key] = false;
});
return collapsedState;
}
default:
throw new Error(`invalid card expansion type: ${action.type}`);
}
};
import { CardExpansionContext } from '../../CardExpansionContext';

const DetailsTab = ({ response, status, hostName }) => {
useEffect(() => {
Expand All @@ -58,8 +17,7 @@ const DetailsTab = ({ response, status, hostName }) => {
registerCoreCards();
return () => document.body.classList.remove('pf-gray-background');
}, []);

const [cardExpandStates, dispatch] = useReducer(cardExpansionReducer, {});
const { cardExpandStates, dispatch } = useContext(CardExpansionContext);
const areAllCardsExpanded = Object.values(cardExpandStates).every(
value => value === true
);
Expand All @@ -68,25 +26,6 @@ const DetailsTab = ({ response, status, hostName }) => {

const collapseAllCards = () => dispatch({ type: 'collapseAll' });

// On mount, get values from localStorage and set them in state
const initializeCardFromLocalStorage = useCallback(key => {
const value = localStorage.getItem(`${key} card expanded`);
if (value !== null && value !== undefined) {
dispatch({ type: value === 'true' ? 'expand' : 'collapse', key });
} else {
dispatch({ type: 'add', key });
}
}, []);

// On unmount, save the values to local storage
// eslint-disable-next-line arrow-body-style
useEffect(() => {
return () =>
Object.entries(cardExpandStates).forEach(([key, value]) =>
localStorage.setItem(`${key} card expanded`, value)
);
});

const buttonText = areAllCardsExpanded
? __('Collapse all cards')
: __('Expand all cards');
Expand All @@ -109,21 +48,13 @@ const DetailsTab = ({ response, status, hostName }) => {
flexWrap={{ default: 'wrap' }}
className="details-tab-flex-container"
>
<CardExpansionContext.Provider
value={{
cardExpandStates,
dispatch,
registerCard: initializeCardFromLocalStorage,
}}
>
<Slot
hostDetails={response}
status={status}
hostName={hostName}
id="host-tab-details-cards"
multi
/>
</CardExpansionContext.Provider>
<Slot
hostDetails={response}
status={status}
hostName={hostName}
id="host-tab-details-cards"
multi
/>
</Flex>
</div>
);
Expand Down
Expand Up @@ -13,7 +13,7 @@ import {
FlexItem,
} from '@patternfly/react-core';

import { CardExpansionContext } from '../../../Tabs/Details';
import { CardExpansionContext } from '../../../CardExpansionContext';

const CardTemplate = ({
header,
Expand Down
Expand Up @@ -41,6 +41,7 @@ import RedirectToEmptyHostPage from './EmptyState';
import BreadcrumbBar from '../BreadcrumbBar';
import { foremanUrl } from '../../common/helpers';
import { useForemanSettings } from '../../Root/Context/ForemanContext';
import { CardExpansionContextWrapper } from './CardExpansionContext';

const HostDetails = ({
match: {
Expand Down Expand Up @@ -227,29 +228,31 @@ const HostDetails = ({
</SkeletonLoader>
</div>
{tabs && (
<TabRouter
response={response}
hostName={id}
status={status}
tabs={tabs}
router={history}
>
<Tabs
ouiaId="host-details-tabs"
activeKey={activeTab}
className={`host-details-tabs tab-width-${
isNavCollapsed ? '138' : '263'
}`}
<CardExpansionContextWrapper>
<TabRouter
response={response}
hostName={id}
status={status}
tabs={tabs}
router={history}
>
{filteredTabs.map(tab => (
<Tab
key={tab}
eventKey={tab}
title={slotMetadata?.[tab]?.title || tab}
/>
))}
</Tabs>
</TabRouter>
<Tabs
ouiaId="host-details-tabs"
activeKey={activeTab}
className={`host-details-tabs tab-width-${
isNavCollapsed ? '138' : '263'
}`}
>
{filteredTabs.map(tab => (
<Tab
key={tab}
eventKey={tab}
title={slotMetadata?.[tab]?.title || tab}
/>
))}
</Tabs>
</TabRouter>
</CardExpansionContextWrapper>
)}
</PageSection>
</>
Expand Down