Project

General

Profile

Download (5.43 KB) Statistics
| Branch: | Tag: | Revision:
/* eslint-disable camelcase */
import PropTypes from 'prop-types';
import React, { useEffect } from 'react';
import { useSelector, shallowEqual } from 'react-redux';
import {
Flex,
FlexItem,
Grid,
Tab,
Tabs,
GridItem,
Badge,
Title,
Breadcrumb,
BreadcrumbItem,
Text,
TextVariants,
PageSection,
Split,
SplitItem,
} from '@patternfly/react-core';

import Skeleton from 'react-loading-skeleton';
import RelativeDateTime from '../../components/common/dates/RelativeDateTime';

import { selectFillsIDs } from '../common/Slot/SlotSelectors';
import { selectIsCollapsed } from '../Layout/LayoutSelectors';
import ActionsBar from './ActionsBar';
import { registerCoreTabs } from './Tabs';
import { HOST_DETAILS_API_OPTIONS } from './consts';

import { translate as __, sprintf } from '../../common/I18n';
import HostGlobalStatus from './Status/GlobalStatus';
import SkeletonLoader from '../common/SkeletonLoader';
import { STATUS } from '../../constants';
import './HostDetails.scss';
import { useAPI } from '../../common/hooks/API/APIHooks';
import TabRouter from './Tabs/TabRouter';
import ExperimentalAlert from './ExperimentalAlert';

const HostDetails = ({
match: {
params: { id },
},
location: { hash },
history,
}) => {
const { response, status } = useAPI(
'get',
`/api/hosts/${id}`,
HOST_DETAILS_API_OPTIONS
);

const isNavCollapsed = useSelector(selectIsCollapsed);
const tabs = useSelector(
state => selectFillsIDs(state, 'host-details-page-tabs'),
shallowEqual
);

// This is a workaround due to the tabs overflow mechanism in PF4
useEffect(() => {
if (tabs?.length) dispatchEvent(new Event('resize'));
}, [tabs]);

useEffect(() => {
registerCoreTabs();
}, []);

return (
<>
<PageSection
className="host-details-header-section"
isFilled
variant="light"
>
<div style={{ marginLeft: '18px', marginRight: '18px' }}>
<Breadcrumb style={{ marginTop: '15px' }}>
<BreadcrumbItem to="/hosts">{__('Hosts')}</BreadcrumbItem>
<BreadcrumbItem isActive>
{response.name || <Skeleton />}
</BreadcrumbItem>
</Breadcrumb>
{/* TODO: Replace all br with css */}
<br />
<br />
<Grid>
<GridItem span={9}>
<SkeletonLoader status={status || STATUS.PENDING}>
{response && (
<>
<div className="hostname-wrapper">
<SkeletonLoader status={status || STATUS.PENDING}>
{response && (
<Title
className="hostname-truncate"
headingLevel="h5"
size="2xl"
>
{response.name}
</Title>
)}
</SkeletonLoader>
</div>
<Split style={{ display: 'inline-flex' }} hasGutter>
<SplitItem>
<HostGlobalStatus hostName={id} />
</SplitItem>
<SplitItem>
<Badge> {response?.operatingsystem_name}</Badge>
</SplitItem>
<SplitItem>
<Badge>{response?.architecture_name}</Badge>
</SplitItem>
</Split>
</>
)}
</SkeletonLoader>
</GridItem>
<GridItem offset={10} span={2}>
<Flex>
<FlexItem align={{ default: 'alignRight' }}>
<ActionsBar hostId={id} permissions={response.permissions} />
</FlexItem>
</Flex>
</GridItem>
</Grid>
<SkeletonLoader
skeletonProps={{ width: 400 }}
status={status || STATUS.PENDING}
>
{response && (
<Text component={TextVariants.span}>
<RelativeDateTime date={response.created_at} defaultValue="N/A">
{date =>
sprintf(__('Created %s by %s'), date, response.owner_name)
}
</RelativeDateTime>{' '}
<RelativeDateTime date={response.updated_at} defaultValue="N/A">
{date => sprintf(__('(updated %s)'), date)}
</RelativeDateTime>
</Text>
)}
</SkeletonLoader>
</div>
<ExperimentalAlert hostId={id} />
{tabs && (
<TabRouter
response={response}
hostName={id}
status={status}
tabs={tabs}
router={history}
>
<Tabs
style={{
width: window.innerWidth - (isNavCollapsed ? 95 : 220),
}}
activeKey={hash.slice(2).split('/')[0]}
>
{tabs.map(tab => (
<Tab key={tab} eventKey={tab} title={tab} href={`#/${tab}`} />
))}
</Tabs>
</TabRouter>
)}
</PageSection>
</>
);
};

HostDetails.propTypes = {
match: PropTypes.shape({
params: PropTypes.shape({
id: PropTypes.string,
}),
}).isRequired,
location: PropTypes.shape({
hash: PropTypes.string,
}).isRequired,
history: PropTypes.object.isRequired,
};

export default HostDetails;
(4-4/4)