@patternfly/react-core#Title JavaScript Examples
The following examples show how to use
@patternfly/react-core#Title.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.js From ocp-advisor-frontend with Apache License 2.0 | 6 votes |
ClustersList = () => {
const intl = useIntl();
insights.chrome.updateDocumentTitle(
intl.formatMessage(messages.documentTitle, {
subnav: intl.formatMessage(messages.clusters),
})
);
return (
<React.Fragment>
<PageHeader className="ins-c-clusters-header">
<Title headingLevel="h1" ouiaId="page-header">
{`${intl.formatMessage(messages.insightsHeader)} ${intl
.formatMessage(messages.clusters)
.toLowerCase()}`}
</Title>
</PageHeader>
<Main>
<ClustersListTable />
</Main>
</React.Fragment>
);
}
Example #2
Source File: tablestates.js From ibutsu-server with MIT License | 6 votes |
render() {
return (
<Bullseye>
<EmptyState>
<EmptyStateIcon icon={ErrorCircleOIcon} />
<Title headingLevel="h5" size="lg">Error occurred fetching results</Title>
{!!this.props.onClearFilters &&
<React.Fragment>
<EmptyStateBody>
An error occurred while fetching results. Try a different set of filters.
</EmptyStateBody>
<EmptyStateSecondaryActions>
<Button variant="link" onClick={this.props.onClearFilters}>Clear all filters</Button>
</EmptyStateSecondaryActions>
</React.Fragment>
}
</EmptyState>
</Bullseye>
);
}
Example #3
Source File: tablestates.js From ibutsu-server with MIT License | 6 votes |
render() {
return (
<Bullseye>
<EmptyState>
<EmptyStateIcon icon={SearchIcon} />
<Title headingLevel="h5" size="lg">No results found</Title>
{!!this.props.onClearFilters &&
<React.Fragment>
<EmptyStateBody>
No results match this filter criteria. Clear all filters to show results.
</EmptyStateBody>
<EmptyStateSecondaryActions>
<Button variant="link" onClick={this.props.onClearFilters}>Clear all filters</Button>
</EmptyStateSecondaryActions>
</React.Fragment>
}
</EmptyState>
</Bullseye>
);
}
Example #4
Source File: NoResultsTable.js From tasks-frontend with Apache License 2.0 | 6 votes |
NoResultsTable = ({ type }) => (
<EmptyTable>
<Bullseye>
<EmptyState variant={EmptyStateVariant.full}>
<Title headingLevel="h5" size="lg">
{`No matching ${type} found`}
</Title>
<EmptyStateBody>
To continue, edit your filter settings and search again.
</EmptyStateBody>
</EmptyState>
</Bullseye>
</EmptyTable>
)
Example #5
Source File: EmptyStateDisplay.js From tasks-frontend with Apache License 2.0 | 6 votes |
EmptyStateDisplay = ({
button,
color,
error,
icon,
isSmall,
text,
title,
}) => {
return (
<EmptyState
variant={isSmall ? EmptyStateVariant.small : EmptyStateVariant.large}
>
{icon ? (
<EmptyStateIcon
icon={icon}
color={color ? color : null}
className={isSmall ? 'small-empty-state-icon' : null}
/>
) : null}
<br></br>
<Title headingLevel={isSmall ? 'h5' : 'h1'} size={isSmall ? 'md' : 'lg'}>
{title}
</Title>
<EmptyStateBody>
{text
? text.map((line, index) => (
<React.Fragment key={`line-${index}`}>
{line}
<br />
</React.Fragment>
))
: null}
{error ? error : null}
</EmptyStateBody>
{button}
</EmptyState>
);
}
Example #6
Source File: NoActivationKeysFound.js From sed-frontend with Apache License 2.0 | 6 votes |
NoActivationKeysFound = (props) => {
const { handleModalToggle } = props;
return (
<>
<EmptyState>
<EmptyStateIcon icon={AddCircleOIcon} />
<Title headingLevel="h5" size="lg">
No activation keys
</Title>
<EmptyStateBody>
You currently have no activation keys to display. Activation keys
allow you to register a system with system purpose, role and usage
attached.
</EmptyStateBody>
<CreateActivationKeyButton onClick={handleModalToggle} />
</EmptyState>
</>
);
}
Example #7
Source File: no-access.js From sed-frontend with Apache License 2.0 | 6 votes |
NoAccessView = () => (
<Bullseye>
<EmptyState>
<EmptyStateIcon icon={LockIcon} />
<Title headingLevel="h4" size="lg">
Activation keys can only be accessed by organization administrators.
</Title>
<EmptyStateBody>
If you already know your organization ID and activation key, you can
register systems with RHC.
</EmptyStateBody>
</EmptyState>
</Bullseye>
)
Example #8
Source File: index.js From ocp-advisor-frontend with Apache License 2.0 | 6 votes |
RecsList = () => {
const intl = useIntl();
insights.chrome.updateDocumentTitle(
intl.formatMessage(messages.documentTitle, {
subnav: intl.formatMessage(messages.recommendations),
})
);
return (
<React.Fragment>
<PageHeader className="ins-c-recommendations-header">
<Title headingLevel="h1" ouiaId="page-header">
{`${intl.formatMessage(messages.insightsHeader)} ${intl
.formatMessage(messages.recommendations)
.toLowerCase()}`}
</Title>
</PageHeader>
<Main>
<Suspense fallback={<Loading />}>
<RecsListTable />
</Suspense>
</Main>
</React.Fragment>
);
}
Example #9
Source File: MessageState.js From ocp-advisor-frontend with Apache License 2.0 | 6 votes |
MessageState = ({ className, children, icon, iconClass, iconStyle, text, title, variant, }) => ( <EmptyState className={className} variant={variant} data-ouia-component-id="empty-state" data-ouia-component-type="PF4/EmptyState" data-ouia-safe={true} > {icon && ( <EmptyStateIcon className={iconClass} style={iconStyle} icon={icon} /> )} <Title headingLevel="h5" size="lg"> {title} </Title> <EmptyStateBody style={{ marginBottom: '16px' }}>{text}</EmptyStateBody> {children} </EmptyState> )
Example #10
Source File: EmptyStates.js From ocp-advisor-frontend with Apache License 2.0 | 6 votes |
NoRecsForClusters = () => {
const intl = useIntl();
return (
<EmptyState variant="small">
<EmptyStateIcon icon={PlusCircleIcon} />
<Title headingLevel="h2" size="2xl">
{intl.formatMessage(messages.noRecsForClusterListTitle)}
</Title>
<EmptyStateBody>
{intl.formatMessage(messages.noRecsForClusterListBody)}
</EmptyStateBody>
<Button
component="a"
variant="primary"
href="https://console.redhat.com/openshift/create"
>
Create cluster
</Button>
<EmptyStateSecondaryActions>
<Button
component="a"
variant="link"
href="https://console.redhat.com/openshift/register"
>
Register cluster
</Button>
<Button
component="a"
variant="link"
href="https://console.redhat.com/openshift/assisted-installer/clusters"
>
Assisted Installer clusters
</Button>
</EmptyStateSecondaryActions>
</EmptyState>
);
}
Example #11
Source File: EmptyStates.js From ocp-advisor-frontend with Apache License 2.0 | 6 votes |
ComingSoon = () => {
const intl = useIntl();
return (
<EmptyState variant="small" id="coming-soon-message">
<EmptyStateIcon icon={InProgressIcon} color="#151515" />
<Title headingLevel="h2" size="2xl">
{intl.formatMessage(messages.comingSoonTitle)}
</Title>
<EmptyStateBody>
{intl.formatMessage(messages.comingSoonBody)}
</EmptyStateBody>
<Link to="/recommendations">
<Button variant="primary">Recommendations</Button>
</Link>
</EmptyState>
);
}
Example #12
Source File: EmptyAccount.js From malware-detection-frontend with Apache License 2.0 | 6 votes |
EmptyAccount = ({ message, className }) => {
const intl = useIntl();
return (
<EmptyState className={className} variant='large'>
<EmptyStateIcon icon={WrenchIcon} />
<Title headingLevel="h4" size="lg">
{intl.formatMessage(messages.emptyAccountTitle)}
</Title>
<EmptyStateBody>
{message}
</EmptyStateBody>
<Button
variant="primary"
component="a"
href={'https://access.redhat.com/documentation/en-us/red_hat_insights/2022/html/' +
'assessing_and_reporting_malware_signatures_on_rhel_systems_with_the_insights_for' +
'_rhel_malware_service/'}
target="_blank" >
{intl.formatMessage(messages.emptyAccountButton)}
</Button>
</EmptyState>
);
}
Example #13
Source File: BuildModalReview.js From edge-frontend with Apache License 2.0 | 6 votes |
BuildModalReview = ({ reviewObject, key }) => {
return (
<TextContent>
<Title headingLevel="h3">
<Text component={'b'}>{reviewObject.title}</Text>
</Title>
<TextList component={TextListVariants.dl}>
{reviewObject.rows.map((row) => (
<Fragment key={row.title + key}>
<TextListItem component={TextListItemVariants.dt}>
{row.title}
</TextListItem>
<TextListItem component={TextListItemVariants.dd}>
{row.value}
</TextListItem>
</Fragment>
))}
</TextList>
</TextContent>
);
}
Example #14
Source File: Loading.js From content-preview with Apache License 2.0 | 6 votes |
Loading = () => {
const Spinner = () => (
<span className="pf-c-spinner" role="progressbar" aria-valuetext="Loading...">
<span className="pf-c-spinner__clipper" />
<span className="pf-c-spinner__lead-ball" />
<span className="pf-c-spinner__tail-ball" />
</span>
);
return (
<EmptyState>
<EmptyStateIcon variant="container" component={Spinner} />
<Title size="lg" headingLevel="h4">
Loading
</Title>
</EmptyState>
);
}
Example #15
Source File: LoadError.js From content-preview with Apache License 2.0 | 6 votes |
LoadDetailError = (props) => {
let bodyMessage;
if (props.bodyMessage === 'List') {
bodyMessage = 'Try again later. Or report issue to @insights-rule-dev';
} else if (props.bodyMessage === 'Detail') {
bodyMessage = 'Use a right PluginName|ErrorKey in URL and try again... Or report issue to @insights-rule-dev';
}
return (
<EmptyState>
<EmptyStateIcon icon={BanIcon} />
<Title size="lg" headingLevel="h4">
Loading Error of {props.bodyMessage}
</Title>
<EmptyStateBody>
{bodyMessage}
</EmptyStateBody>
<EmptyStatePrimary>
Back to <Link to='/preview'>Content Preview</Link>
</EmptyStatePrimary>
</EmptyState>
);
}
Example #16
Source File: AccessRequestsPage.js From access-requests-frontend with Apache License 2.0 | 6 votes |
AccessRequestsPage = ({ isInternal }) => {
return (
<Provider store={registry.getStore()}>
<ErroReducerCatcher>
<PageSection variant="light">
<Title headingLevel="h1" className="pf-u-pb-sm">
Access Requests
</Title>
<p>
Below is a list of all submitted requests for read only account
access.
</p>
</PageSection>
<PageSection padding={{ default: 'noPadding' }}>
<AccessRequestsTable isInternal={isInternal} />
</PageSection>
</ErroReducerCatcher>
</Provider>
);
}
Example #17
Source File: InactiveServicePage.js From cockpit-wicked with GNU General Public License v2.0 | 6 votes |
InactiveServicePage = () => {
return (
<EmptyState>
<EmptyStateIcon icon={AlertIcon} />
<Title headingLevel="h4" size="lg">
{_("Wicked service is not active")}
</Title>
<EmptyStateBody>
<p>
{_(`Seems that wicked service is not active. It could be either, the service is
not running or wicked is not installed.`)}
</p>
<p>
{_("For more help, please check the documentation linked below.")}
</p>
</EmptyStateBody>
<EmptyStateSecondaryActions>
<ExternalLink href="https://en.opensuse.org/Portal:Wicked">
openSUSE Wicked Portal
</ExternalLink>
<ExternalLink href="https://github.com/openSUSE/wicked/wiki/FAQ">
Wicked FAQ
</ExternalLink>
<ExternalLink href="https://github.com/openSUSE/wicked">
Public Wicked Repository
</ExternalLink>
</EmptyStateSecondaryActions>
</EmptyState>
);
}
Example #18
Source File: RoutingTab.js From cockpit-wicked with GNU General Public License v2.0 | 6 votes |
RoutingTab = () => {
const dispatch = useNetworkDispatch();
const { routes } = useNetworkState();
useEffect(() => { fetchRoutes(dispatch) }, [dispatch]);
const routesList = routes ? Object.values(routes) : [];
const routesNotFound = () => (
<EmptyState>
<EmptyStateIcon icon={InfoCircleIcon} />
<Title headingLevel="h4" size="lg">
{_('No user-defined routes were found.')}
</Title>
<AddRoute />
</EmptyState>
);
if (routesList.length === 0) {
return routesNotFound();
}
return (
<Card>
<CardHeader>
<CardActions>
<AddRoute />
</CardActions>
<CardTitle>
<Text component={TextVariants.h2}>{_("User-defined Routes")}</Text>
</CardTitle>
</CardHeader>
<CardBody>
<RoutesList routes={routesList} />
</CardBody>
</Card>
);
}
Example #19
Source File: Empty.js From edge-frontend with Apache License 2.0 | 5 votes |
Empty = ({ bgColor, icon, title, body, primaryAction, secondaryActions, }) => ( <EmptyState variant="large" style={{ backgroundColor: bgColor || '' }}> {icon && <EmptyStateIcon icon={iconMapper[icon]} />} <Title headingLevel="h4" size="lg"> {title} </Title> <EmptyStateBody>{body}</EmptyStateBody> {primaryAction && ( <> {primaryAction.href ? ( <Button component={Link} to={primaryAction.href}> {primaryAction.text} </Button> ) : ( <Button onClick={primaryAction.click} variant="primary"> {primaryAction.text} </Button> )} </> )} <EmptyStateSecondaryActions> {secondaryActions.map(({ type, title, link, onClick }, index) => ( <Button component={type === 'link' ? 'a' : 'button'} href={link} variant="link" target={type === 'link' ? '_blank' : ''} key={index} onClick={onClick} > {title} {link && <ExternalLinkAltIcon className="pf-u-ml-sm" />} </Button> ))} </EmptyStateSecondaryActions> </EmptyState> )
Example #20
Source File: project-edit.js From ibutsu-server with MIT License | 5 votes |
render() {
const { project, users, owner } = this.state;
return (
<React.Fragment>
<PageSection variant={PageSectionVariants.light}>
<Title headingLevel="h1" size='2xl' className="pf-c-title">
Projects / {project && project.title}
</Title>
</PageSection>
<PageSection>
{!project && <Alert variant="info" title="Loading..." />}
{project &&
<Card>
<CardBody>
<Form>
<FormGroup label="Title" isRequired fieldId="projectTitle" helperText="The project's friendly name">
<TextInput
isRequired
type="text"
id="projectTitle"
name="projectTitle"
aria-describedby="The project's friendly name"
value={project.title}
onChange={this.onProjectTitleChanged}
/>
</FormGroup>
<FormGroup label="Name" isRequired fieldId="projectName" helperText="The project's machine name">
<TextInput
isRequired
type="text"
id="projectName"
name="projectName"
aria-describedby="The project's machine name"
value={project.name}
onChange={this.onProjectNameChanged}
/>
</FormGroup>
<FormGroup fieldId="owner" label="Owner" helperText="The user who owns the project">
<Select
variant={SelectVariant.typeahead}
typeAheadAriaLabel="Select user"
onToggle={this.onOwnerToggle}
onSelect={this.onOwnerSelect}
onClear={this.onOwnerClear}
onTypeaheadInputChanged={this.onOwnerChanged}
selections={owner}
isOpen={this.state.isOwnerOpen}
aria-labelledby="owner"
placeholderText="Select user"
>
{users.map(user => (
<SelectOption key={user.id} value={userToOption(user)} description={user.email} />
))}
</Select>
</FormGroup>
<ActionGroup>
<Button
variant="primary"
ouiaId="admin-project-edit-save"
onClick={this.onSubmitClick}
>
Submit
</Button>
<Button
variant="secondary"
ouiaId="admin-project-edit-cancel"
component={(props: any) => <Link {...props} to="/admin/projects" />}
>
Cancel
</Button>
</ActionGroup>
</Form>
</CardBody>
</Card>
}
</PageSection>
</React.Fragment>
);
}
Example #21
Source File: ModalConfirm.js From cockpit-wicked with GNU General Public License v2.0 | 5 votes |
ModalConfirm = ({
caption,
title,
isOpen = false,
onConfirm,
onConfirmDisable = false,
onConfirmLabel = _("Confirm"),
onCancel,
onCancelLabel = _("Cancel"),
variant = ModalVariant.small,
children
}) => {
if (!isOpen) return;
return (
<Modal
aria-label={title}
variant={variant}
isOpen={isOpen}
showClose={false}
header={
<>
<Text component={TextVariants.small} className='modal-form-caption'>
{caption}
</Text>
<Title headingLevel="h1">
{title}
</Title>
</>
}
footer={
<ActionGroup>
<Button key="confirm" variant="danger" onClick={onConfirm}>
{onConfirmLabel}
</Button>
<Button key="cancel" variant="link" onClick={onCancel}>
{onCancelLabel}
</Button>
</ActionGroup>
}
>
{children}
</Modal>
);
}
Example #22
Source File: ModalForm.js From cockpit-wicked with GNU General Public License v2.0 | 5 votes |
ModalForm = ({
caption,
title,
isOpen = false,
onSubmit,
onSubmitDisable = false,
onSubmitLabel = _("Apply"),
onCancel,
onCancelLabel = _("Cancel"),
variant = ModalVariant.small,
children
}) => {
if (!isOpen) return;
return (
<Modal
aria-label={title}
variant={variant}
isOpen={isOpen}
showClose={false}
header={
<>
<Text component={TextVariants.small} className='modal-form-caption'>
{caption}
</Text>
<Title headingLevel="h1">
{title}
</Title>
</>
}
footer={
<ActionGroup>
<Button key="submit" onClick={onSubmit} isDisabled={onSubmitDisable}>
{onSubmitLabel}
</Button>
<Button key="cancel" variant="link" onClick={onCancel}>
{onCancelLabel}
</Button>
</ActionGroup>
}
>
<Form>
{children}
</Form>
</Modal>
);
}
Example #23
Source File: user-edit.js From ibutsu-server with MIT License | 4 votes |
render() {
const { user, projects, userProjects } = this.state;
return (
<React.Fragment>
<PageSection variant={PageSectionVariants.light}>
<Title headingLevel="h1" size='2xl' className="pf-c-title">
Users / {user && user.name} {' '}
{user && user.is_superadmin &&
<Label className="super-admin-label" variant="outline" color="blue">Administrator</Label>
}
</Title>
</PageSection>
<PageSection>
{!user && <Alert variant="info" title="Loading..." />}
{user &&
<Card>
<CardBody>
<Form>
<FormGroup label="Name" isRequired fieldId="userName" helperText="The user's name">
<TextInput
isRequired
type="text"
id="userName"
name="userName"
aria-describedby="The user's name"
value={user.name}
onChange={this.onUserNameChanged}
/>
</FormGroup>
<FormGroup label="E-mail" isRequired fieldId="userEmail" helperText="The user's e-mail address">
<TextInput
isRequired
type="email"
id="userEmail"
name="userEmail"
aria-describedby="The user's e-mail address"
value={user.email}
onChange={this.onUserEmailChanged}
/>
</FormGroup>
<FormGroup fieldId="userStatus" label="User status">
<Checkbox
label="Is active"
id="userIsActive"
name="userIsActive"
aria-label="User is active"
isChecked={user.is_active}
onChange={this.onIsActiveToggle}
/>
<Checkbox
label="Is administrator"
id="userIsAdmin"
name="userIsAdmin"
aria-label="User is administrator"
isChecked={user.is_superadmin}
onChange={this.onIsAdminToggle}
/>
</FormGroup>
<FormGroup fieldId="userProjects" label="Projects" helperText="The projects to which a user has access">
<Select
variant={SelectVariant.typeaheadMulti}
typeAheadAriaLabel="Select one or more projects"
onToggle={this.onProjectsToggle}
onSelect={this.onProjectsSelect}
onClear={this.onProjectsClear}
selections={userProjects}
isOpen={this.state.isProjectsOpen}
aria-labelledby="userProjects"
placeholderText="Select one or more projects"
>
{projects.map(project => (
<SelectOption key={project.id} value={projectToOption(project)} description={project.name} />
))}
</Select>
</FormGroup>
<ActionGroup>
<Button variant="primary" onClick={this.onSubmitClick}>Submit</Button>
<Button variant="secondary" onClick={this.props.history.goBack}>Cancel</Button>
</ActionGroup>
</Form>
</CardBody>
</Card>
}
</PageSection>
</React.Fragment>
);
}
Example #24
Source File: Recommendation.js From ocp-advisor-frontend with Apache License 2.0 | 4 votes |
Recommendation = ({ rule, ack, clusters, match }) => {
const intl = useIntl();
const dispatch = useDispatch();
const notify = (data) => dispatch(addNotification(data));
const recId = match.params.recommendationId;
const [disableRuleModalOpen, setDisableRuleModalOpen] = useState(false);
const [actionsDropdownOpen, setActionsDropdownOpen] = useState(false);
const [viewSystemsModalOpen, setViewSystemsModalOpen] = useState(false);
// rule's info
const {
isError,
isUninitialized,
isLoading,
isFetching,
isSuccess,
data,
refetch,
} = rule;
// justification note, last time acknowledged, etc.
const { data: ackData, isFetching: ackIsFetching, refetch: refetchAck } = ack;
const ruleDate = new Date(ackData?.updated_at || ackData?.created_at);
// affected and acked clusters lists
const {
data: clustersData,
isFetching: clustersIsFetching,
refetch: refetchClusters,
} = clusters;
const content =
isSuccess && data ? adjustOCPRule(data.content, recId) : undefined;
const ackedClusters =
!clustersIsFetching && clustersData ? clustersData.disabled : undefined;
const afterDisableFn = async () => {
refetch();
refetchAck();
refetchClusters();
};
const handleModalToggle = (disableRuleModalOpen) => {
setDisableRuleModalOpen(disableRuleModalOpen);
};
const enableRecForHosts = async ({ uuids }) => {
try {
const requests = uuids.map((uuid) =>
enableRuleForCluster({ uuid, recId })
);
await Promise.all(requests);
refetch();
refetchAck();
refetchClusters();
notify({
variant: 'success',
timeout: true,
dismissable: true,
title: intl.formatMessage(messages.recSuccessfullyEnabledForCluster),
});
} catch (error) {
notify({
variant: 'danger',
dismissable: true,
title: intl.formatMessage(messages.error),
description: `${error}`,
});
}
};
const enableRule = async (rule) => {
try {
await Delete(`${BASE_URL}/v2/ack/${rule.data.content.rule_id}/`);
notify({
variant: 'success',
timeout: true,
dismissable: true,
title: intl.formatMessage(messages.recSuccessfullyEnabled),
});
refetch();
} catch (error) {
handleModalToggle(false);
notify({
variant: 'danger',
dismissable: true,
title: intl.formatMessage(messages.error),
description: `${error}`,
});
}
};
const messagesValues = useMemo(
() => (content ? mapContentToValues(intl, content) : {}),
[intl, content]
);
return (
<React.Fragment>
{viewSystemsModalOpen && (
<ViewHostAcks
handleModalToggle={(toggleModal) =>
setViewSystemsModalOpen(toggleModal)
}
isModalOpen={viewSystemsModalOpen}
clusters={clusters}
afterFn={() => refetchClusters()}
recId={recId}
/>
)}
{disableRuleModalOpen && (
<DisableRule
handleModalToggle={handleModalToggle}
isModalOpen={disableRuleModalOpen}
rule={content}
afterFn={afterDisableFn}
/>
)}
<PageHeader className="pageHeaderOverride">
<Breadcrumbs current={content?.description || recId} />
</PageHeader>
{(isUninitialized || isLoading || isFetching) && (
<Main>
<Loading />
</Main>
)}
{isError && (
<Main>
<ErrorState />
</Main>
)}
{!(isUninitialized || isLoading || isFetching) && isSuccess && (
<React.Fragment>
<Main className="pf-m-light pf-u-pt-sm">
<RuleDetails
messages={formatMessages(
intl,
RuleDetailsMessagesKeys,
messagesValues
)}
product={AdvisorProduct.ocp}
rule={content}
isDetailsPage
header={
<React.Fragment>
<PageHeaderTitle
title={
<React.Fragment>
{content.description} <RuleLabels rule={content} />
</React.Fragment>
}
/>
<p>
{intl.formatMessage(messages.rulesDetailsPubishdate, {
date: (
<DateFormat
date={new Date(content.publish_date)}
type="onlyDate"
/>
),
})}
{content.tags &&
(Array.isArray(content.tags) ? (
<LabelGroup
className="categoryLabels"
numLabels={1}
isCompact
>
{content.tags.reduce((labels, tag) => {
if (RULE_CATEGORIES[tag]) {
labels.push(
<Label
key={`label-${tag}`}
color="blue"
isCompact
>
{
FILTER_CATEGORIES.category.values[
RULE_CATEGORIES[tag] - 1
].label
}
</Label>
);
}
return labels;
}, [])}
</LabelGroup>
) : (
<Label isCompact>{content.tags}</Label>
))}
</p>
</React.Fragment>
}
onVoteClick={async (rule, rating) =>
await Post(`${BASE_URL}/v2/rating`, {}, { rule, rating })
}
>
<Flex>
<FlexItem align={{ default: 'alignRight' }}>
<Dropdown
className="ins-c-rec-details__actions_dropdown"
onSelect={() =>
setActionsDropdownOpen(!actionsDropdownOpen)
}
position="right"
ouiaId="actions"
toggle={
<DropdownToggle
onToggle={(actionsDropdownOpen) =>
setActionsDropdownOpen(actionsDropdownOpen)
}
toggleIndicator={CaretDownIcon}
>
{intl.formatMessage(messages.actions)}
</DropdownToggle>
}
isOpen={actionsDropdownOpen}
dropdownItems={
content?.disabled
? [
<DropdownItem
key="link"
ouiaId="enable"
onClick={() => {
enableRule(rule);
}}
>
{intl.formatMessage(messages.enableRule)}
</DropdownItem>,
]
: [
<DropdownItem
key="link"
ouiaId="disable"
onClick={() => {
handleModalToggle(true);
}}
>
{intl.formatMessage(messages.disableRule)}
</DropdownItem>,
]
}
/>
</FlexItem>
</Flex>
</RuleDetails>
</Main>
<Main>
<React.Fragment>
{(content?.hosts_acked_count ||
ackedClusters?.length > 0 ||
content?.disabled) && (
<Card className="cardOverride" ouiaId="hosts-acked">
<CardHeader>
<Title headingLevel="h4" size="xl">
<BellSlashIcon size="sm" />
{intl.formatMessage(
(content?.hosts_acked_count ||
ackedClusters?.length > 0) &&
!content?.disabled
? messages.ruleIsDisabledForClusters
: messages.ruleIsDisabled
)}
</Title>
</CardHeader>
<CardBody>
{(content?.hosts_acked_count ||
ackedClusters?.length > 0) &&
!content?.disabled ? (
<React.Fragment>
{intl.formatMessage(
messages.ruleIsDisabledForClustersBody,
{
clusters: ackedClusters?.length,
}
)}
{!clustersIsFetching && ackedClusters?.length > 0 ? (
<React.Fragment>
<Button
isInline
variant="link"
onClick={() => setViewSystemsModalOpen(true)}
ouiaId="view-clusters"
>
{intl.formatMessage(messages.viewClusters)}
</Button>
</React.Fragment>
) : (
<OneLineLoader />
)}
</React.Fragment>
) : (
!ackIsFetching &&
ackData && (
<React.Fragment>
{ackData?.justification
? intl.formatMessage(
messages.ruleIsDisabledWithJustificaiton,
{
date: (
<span>
<DateFormat
date={ruleDate}
type="onlyDate"
/>
</span>
),
reason: ackData.justification,
}
)
: intl.formatMessage(
messages.ruleIsDisabledWithoutJustificaiton,
{
date: (
<span>
<DateFormat
date={ruleDate}
type="onlyDate"
/>
</span>
),
}
)}
</React.Fragment>
)
)}
</CardBody>
<CardFooter>
{(content?.hosts_acked_count ||
ackedClusters?.length > 0) &&
!content?.disabled ? (
!clustersIsFetching && ackedClusters ? (
<Button
isInline
variant="link"
onClick={() =>
enableRecForHosts({
uuids: ackedClusters.map((c) => c.cluster_id),
})
}
ouiaId="enable"
>
{intl.formatMessage(messages.enableRuleForClusters)}
</Button>
) : (
<OneLineLoader />
)
) : (
<Button
isInline
variant="link"
onClick={() => enableRule(rule)}
ouiaId="enable"
>
{intl.formatMessage(messages.enableRule)}
</Button>
)}
</CardFooter>
</Card>
)}
{!content?.disabled && (
<React.Fragment>
<Title className="titleOverride" headingLevel="h3" size="2xl">
{intl.formatMessage(messages.affectedClusters)}
</Title>
<AffectedClustersTable
query={clusters}
rule={content}
afterDisableFn={afterDisableFn}
/>
</React.Fragment>
)}
{content?.disabled && (
<MessageState
icon={BellSlashIcon}
title={intl.formatMessage(messages.ruleIsDisabled)}
text={intl.formatMessage(messages.ruleIsDisabledBody)}
/>
)}
</React.Fragment>
</Main>
</React.Fragment>
)}
</React.Fragment>
);
}
Example #25
Source File: user.js From ibutsu-server with MIT License | 4 votes |
render() {
const { user, projects } = this.state;
let projectInfo = [];
// create the project rows
if (projects && user) {
projectInfo.push(projects.map((project) => (
<DataListCell key={project.name} className="pf-u-p-sm">
<span> {project.title} </span>
{project.owner_id === user.id &&
<Label className="project-owner-label" variant="filled" color="green" isCompact>Owner</Label>
}
</DataListCell>
)))
}
return (
<React.Fragment>
<PageSection variant={PageSectionVariants.light}>
<Title headingLevel="h1" size='2xl' className="pf-c-title">
<React.Fragment>
<span> Profile </span>
{user && user.is_superadmin &&
<Label className="super-admin-label" variant="filled" color="blue">Administrator</Label>
}
</React.Fragment>
</Title>
</PageSection>
<PageSection>
{!user && <Alert variant="danger" title="Error fetching user details" />}
{user &&
<DataList selectedDataListItemId={null} aria-label="User profile">
<DataListItem aria-labelledby="Name">
<DataListItemRow>
{!this.state.isEditing &&
<DataListItemCells
dataListCells={[
<DataListCell key={1} width={2}><strong>Name:</strong></DataListCell>,
<DataListCell key={2} width={4}>{user.name} <Button variant="link" icon={<PencilAltIcon />} onClick={this.onEditButtonClicked} isInline isSmall ouiaId="edit-profile-button">Edit</Button></DataListCell>
]}
/>
}
{this.state.isEditing &&
<DataListItemCells
dataListCells={[
<DataListCell key={1} width={2}><strong>Name:</strong></DataListCell>,
<DataListCell key={2} width={4}>
<InputGroup>
<TextInput value={this.state.tempName} type="text" onChange={value => this.setState({tempName: value})} aria-label="User name" />
<Button variant="control" icon={<CheckIcon />} onClick={this.onSaveButtonClicked} ouiaId="edit-save-button">Save</Button>
<Button variant="control" icon={<TimesIcon />} onClick={this.onCancelButtonClicked} ouiaId="edit-cancel-button">Cancel</Button>
</InputGroup>
</DataListCell>
]}
/>
}
</DataListItemRow>
</DataListItem>
<DataListItem aria-labelledby="E-mail">
<DataListItemRow>
<DataListItemCells
dataListCells={[
<DataListCell key={1} width={2}><strong>E-mail:</strong></DataListCell>,
<DataListCell key={2} width={4}>{user.email}</DataListCell>
]}
/>
</DataListItemRow>
</DataListItem>
<DataListItem aria-labelledby="Projects">
<DataListItemRow>
<DataListItemCells
dataListCells={[
<DataListCell key={1} width={2}><strong>My Projects:</strong></DataListCell>,
<DataListCell key={2} width={4} style={{paddingTop: 0, paddingBottom: 0}}>
<DataList aria-lable="projects" style={{borderTop: "none"}}>
{projects &&
projectInfo
}
</DataList>
</DataListCell>
]}
/>
</DataListItemRow>
</DataListItem>
</DataList>
}
</PageSection>
</React.Fragment>
);
}
Example #26
Source File: dashboard.js From ibutsu-server with MIT License | 4 votes |
render() {
document.title = 'Dashboard | Ibutsu';
const { widgets } = this.state;
const project = getActiveProject();
const dashboard = getActiveDashboard();
return (
<React.Fragment>
<PageSection variant={PageSectionVariants.light}>
<Flex justifyContent={{ default: 'justifyContentSpaceBetween' }}>
<Flex>
<FlexItem spacer={{ default: 'spacerLg' }}>
<TextContent>
<Text component="h1">Dashboard</Text>
</TextContent>
</FlexItem>
<FlexItem id="dashboard-selector" spacer={{ default: 'spacerNone' }}>
<Select
ariaLabelTypeAhead="Select a dashboard"
placeholderText="No active dashboard"
variant={SelectVariant.typeahead}
isOpen={this.state.isDashboardSelectorOpen}
isDisabled={!project}
selections={this.state.selectedDashboard}
onToggle={this.onDashboardToggle}
onSelect={this.onDashboardSelect}
onClear={this.onDashboardClear}
onTypeaheadInputChanged={this.onDashboardChanged}
footer={this.state.dashboards.length == 10 && "Search for more..."}
isPlain
>
{this.state.dashboards.map(dash => (
<SelectOption key={dash.id} value={dashboardToSelect(dash)} />
))}
</Select>
</FlexItem>
<FlexItem spacer={{ default: 'spacerNone' }}>
<Button
aria-label="New dashboard"
variant="plain"
title="New dashboard"
isDisabled={!project}
onClick={this.onNewDashboardClick}
>
<PlusCircleIcon />
</Button>
</FlexItem>
<FlexItem>
<Button
aria-label="Delete dashboard"
variant="plain"
title="Delete dashboard"
isDisabled={!dashboard}
onClick={this.onDeleteDashboardClick}
>
<TimesCircleIcon />
</Button>
</FlexItem>
</Flex>
<Flex>
<FlexItem>
<Button
aria-label="Add widget"
variant="secondary"
title="Add widget"
isDisabled={!this.state.selectedDashboard}
onClick={this.onAddWidgetClick}
>
<PlusCircleIcon /> Add Widget
</Button>
</FlexItem>
</Flex>
</Flex>
</PageSection>
<PageSection>
{!!project && !!dashboard && !!widgets &&
<Grid hasGutter>
{widgets.map(widget => {
if (KNOWN_WIDGETS.includes(widget.widget)) {
return (
<GridItem xl={4} lg={6} md={12} key={widget.id}>
{(widget.type === "widget" && widget.widget === "jenkins-heatmap") &&
<JenkinsHeatmapWidget
title={widget.title}
params={widget.params}
includeAnalysisLink={true}
onDeleteClick={() => this.onDeleteWidgetClick(widget.id)}
/>
}
{(widget.type === "widget" && widget.widget === "run-aggregator") &&
<GenericBarWidget
title={widget.title}
params={widget.params}
horizontal={true}
percentData={true}
barWidth={20}
onDeleteClick={() => this.onDeleteWidgetClick(widget.id)}
/>
}
{(widget.type === "widget" && widget.widget === "result-summary") &&
<ResultSummaryWidget
title={widget.title}
params={widget.params}
onDeleteClick={() => this.onDeleteWidgetClick(widget.id)}
/>
}
{(widget.type === "widget" && widget.widget === "result-aggregator") &&
<ResultAggregatorWidget
title={widget.title}
params={widget.params}
onDeleteClick={() => this.onDeleteWidgetClick(widget.id)}
/>
}
</GridItem>
);
}
else {
return '';
}
})}
</Grid>
}
{!project &&
<EmptyState>
<EmptyStateIcon icon={ArchiveIcon} />
<Title headingLevel="h4" size="lg">
No Project Selected
</Title>
<EmptyStateBody>
There is currently no project selected. Please select a project from the dropdown in
order to view the dashboard.
</EmptyStateBody>
</EmptyState>
}
{!!project && !dashboard &&
<EmptyState>
<EmptyStateIcon icon={TachometerAltIcon} />
<Title headingLevel="h4" size="lg">
No Dashboard Selected
</Title>
<EmptyStateBody>
There is currently no dashboard selected. Please select a dashboard from the dropdown
in order to view widgets, or create a new dashboard.
</EmptyStateBody>
<Button variant="primary" onClick={this.onNewDashboardClick}>New Dashboard</Button>
</EmptyState>
}
{(!!project && !!dashboard && widgets.length === 0) &&
<EmptyState>
<EmptyStateIcon icon={CubesIcon} />
<Title headingLevel="h4" size="lg">
No Widgets
</Title>
<EmptyStateBody>
This dashboard currently has no widgets defined.<br />Click on the "Add Widget" button
below to add a widget to this dashboard.
</EmptyStateBody>
<Button variant="primary" onClick={this.onAddWidgetClick}>Add Widget</Button>
</EmptyState>
}
</PageSection>
<NewDashboardModal
project={project}
isOpen={this.state.isNewDashboardOpen}
onSave={this.onNewDashboardSave}
onClose={this.onNewDashboardClose}
/>
<NewWidgetWizard
dashboard={dashboard}
isOpen={this.state.isWidgetWizardOpen}
onSave={this.onNewWidgetSave}
onClose={this.onNewWidgetClose}
/>
<DeleteModal
title="Delete dashboard"
body={<>Would you like to delete the current dashboard? <strong>ALL WIDGETS</strong> on the dashboard will also be deleted.</>}
isOpen={this.state.isDeleteDashboardOpen}
onDelete={this.onDeleteDashboard}
onClose={this.onDeleteDashboardClose}
/>
<DeleteModal
title="Delete widget"
body="Would you like to delete the selected widget?"
isOpen={this.state.isDeleteWidgetOpen}
onDelete={this.onDeleteWidget}
onClose={this.onDeleteWidgetClose}
/>
</React.Fragment>
);
}
Example #27
Source File: new-widget-wizard.js From ibutsu-server with MIT License | 4 votes |
render() {
const { widgetTypes, selectedType, selectedTypeId, stepIdReached, isTitleValid, areParamsFilled } = this.state;
const steps = [
{
id: 1,
name: 'Select type',
enableNext: selectedType,
component: (
<Form>
<Title headingLevel="h1" size="xl">Select a widget type</Title>
{widgetTypes.map(widgetType => {
return (
<div key={widgetType.id}>
<Radio id={widgetType.id} value={widgetType.id} label={widgetType.title} description={widgetType.description} isChecked={selectedTypeId === widgetType.id} onChange={this.onSelectType}/>
</div>
);
})}
</Form>
)
},
{
id: 2,
name: 'Set info',
canJumpTo: stepIdReached >= 2,
enableNext: isTitleValid,
component: (
<Form isHorizontal>
<Title headingLevel="h1" size="xl">Set widget information</Title>
<FormGroup label="Title" fieldId="widget-title" helperText="A title for the widget" validated={this.isTitleValid} helperTextInvalid="Please enter a title for this widget" helperTextInvalidIcon={<ExclamationCircleIcon/>} isRequired>
<TextInput type="text" id="widget-title" name="widget-title" value={this.state.title} onChange={this.onTitleChange} validated={this.state.isTitleValid} isRequired />
</FormGroup>
<FormGroup label="Weight" fieldId="widget-weight" helperText="How widgets are ordered on the dashboard">
<TextInput type="number" id="widget-weight" name="widget-weight" value={this.state.weight} onChange={this.onWeightChange} />
</FormGroup>
</Form>
)
},
{
id: 3,
name: 'Set parameters',
canJumpTo: stepIdReached >= 3,
enableNext: areParamsFilled,
component: (
<Form isHorizontal>
<Title headingLevel="h1" size="xl">Set widget parameters</Title>
{!!selectedType && selectedType.params.map(param => {
return (
<React.Fragment key={param.name}>
{(param.type === 'string' || param.type === 'integer' || param.type === 'float') &&
<FormGroup
label={param.name}
fieldId={param.name}
helperText={<Linkify componentDecorator={linkifyDecorator}>{param.description}</Linkify>}
isRequired={param.required}>
<TextInput
value={this.state.params[param.name]}
type={(param.type === 'integer' || param.type === 'float') ? 'number' : 'text'}
id={param.name}
aria-describedby={`${param.name}-helper`}
name={param.name}
onChange={this.onParamChange}
isRequired={param.required}
/>
</FormGroup>
}
{param.type === 'boolean' &&
<FormGroup
label={param.name}
fieldId={param.name}
isRequired={param.required}
hasNoPaddingTop>
<Checkbox
isChecked={this.state.params[param.name]}
onChange={this.onParamChange}
id={param.name}
name={param.name}
label={param.description} />
</FormGroup>
}
{param.type === 'list' &&
<FormGroup
label={param.name}
fieldId={param.name}
helperText={`${param.description}. Place items on separate lines.`}>
isRequired={param.required}
<TextArea
id={param.name}
name={param.name}
isRequired={param.required}
value={this.state.params[param.name]}
onChange={this.onParamChange}
resizeOrientation='vertical' />
</FormGroup>
}
</React.Fragment>
);
})}
</Form>
)
},
{
id: 4,
name: 'Review details',
canJumpTo: stepIdReached >= 4,
nextButtonText: 'Finish',
component: (
<Stack hasGutter>
<StackItem>
<Title headingLevel="h1" size="xl">Review details</Title>
</StackItem>
<StackItem>
<Grid hasGutter>
<GridItem span="2">
<Title headingLevel="h4">Title</Title>
</GridItem>
<GridItem span="10">
<TextContent><Text>{this.state.title}</Text></TextContent>
</GridItem>
<GridItem span="2">
<Title headingLevel="h4">Weight</Title>
</GridItem>
<GridItem span="10">
<TextContent><Text>{this.state.weight}</Text></TextContent>
</GridItem>
<GridItem span="2">
<Title headingLevel="h4">Parameters</Title>
</GridItem>
<GridItem span="10">
<Table
cells={["Name", "Value"]}
variant="compact"
borders="compactBorderless"
rows={Object.entries(this.state.params).map(param => { return [param[0], param[1].toString()]; })}
aria-label="Parameters">
<TableHeader />
<TableBody />
</Table>
</GridItem>
</Grid>
</StackItem>
</Stack>
)
}
];
return (
<Modal
isOpen={this.props.isOpen}
variant={ModalVariant.large}
showClose={false}
onClose={this.onClose}
hasNoBodyWrapper
aria-describedby="add-widget-description"
aria-labelledby="add-widget-title"
>
<Wizard
titleId="add-widget-title"
descriptionId="add-widget-description"
title="Add Widget"
description="Add a widget to the current dashboard"
steps={steps}
onNext={this.onNext}
onSave={this.onSave}
onClose={this.onClose}
height={400}
/>
</Modal>
);
}
Example #28
Source File: AccessRequestsTable.js From access-requests-frontend with Apache License 2.0 | 4 votes |
AccessRequestsTable = ({ isInternal }) => {
const columns = isInternal
? [
'Request ID',
'Account number',
'Start date',
'End date',
'Created',
'Status',
]
: [
'Request ID',
'First name',
'Last name',
'Start date',
'End date',
'Created',
'Decision',
];
// Sorting
const [activeSortIndex, setActiveSortIndex] = React.useState(
isInternal ? 4 : 5
);
const [activeSortDirection, setActiveSortDirection] = React.useState('desc');
const onSort = (_ev, index, direction) => {
setActiveSortIndex(index);
setActiveSortDirection(direction);
};
// Pagination
const [page, setPage] = React.useState(1);
const [perPage, setPerPage] = React.useState(20);
const AccessRequestsPagination = ({ id }) => (
<Pagination
itemCount={numRows}
perPage={perPage}
page={page}
onSetPage={(_ev, pageNumber) => setPage(pageNumber)}
id={'access-requests-table-pagination-' + id}
variant={id}
perPageOptions={[5, 10, 20, 50].map((n) => ({ title: n, value: n }))}
onPerPageSelect={(_ev, perPage) => {
setPage(1);
setPerPage(perPage);
}}
isCompact={id === 'top'}
/>
);
AccessRequestsPagination.propTypes = {
id: PropTypes.string,
};
// Filtering
const [isDropdownOpen, setIsDropdownOpen] = React.useState(false);
const [filterColumn, setFilterColumn] = React.useState(
columns[isInternal ? 1 : 6]
);
const [isSelectOpen, setIsSelectOpen] = React.useState(false);
const [statusSelections, setStatusSelections] = React.useState([]);
// Harder than it needs to be to match rest of RBAC which doesn't wait
// for user to click a button or press enter.
const [accountFilter, setAccountFilter] = React.useState('');
const [filtersDirty, setFiltersDirty] = React.useState(false);
const hasFilters = statusSelections.length > 0 || accountFilter;
// Row loading
const [isLoading, setIsLoading] = React.useState(true);
const [numRows, setNumRows] = React.useState(0);
const [rows, setRows] = React.useState([]);
const dispatch = useDispatch();
const fetchAccessRequests = () => {
setIsLoading(true);
const listUrl = new URL(
`${window.location.origin}${API_BASE}/cross-account-requests/`
);
isInternal
? listUrl.searchParams.append('query_by', 'user_id')
: listUrl.searchParams.append('query_by', 'target_account');
listUrl.searchParams.append('offset', (page - 1) * perPage);
listUrl.searchParams.append('limit', perPage);
// https://github.com/RedHatInsights/insights-rbac/blob/master/rbac/api/cross_access/view.py
if (accountFilter) {
listUrl.searchParams.append('account', accountFilter);
}
if (statusSelections.length > 0) {
listUrl.searchParams.append('status', statusSelections.join(','));
}
const orderBy = `${activeSortDirection === 'desc' ? '-' : ''}${columns[
activeSortIndex
]
.toLowerCase()
.replace(' ', '_')}`;
listUrl.searchParams.append('order_by', orderBy);
apiInstance
.get(listUrl.href, { headers: { Accept: 'application/json' } })
.then((res) => {
setNumRows(res.meta.count);
setRows(
res.data.map((d) =>
isInternal
? [
d.request_id,
d.target_account,
d.start_date,
d.end_date,
d.created,
d.status,
]
: [
d.request_id,
d.first_name,
d.last_name,
d.start_date,
d.end_date,
d.created,
d.status,
]
)
);
setIsLoading(false);
})
.catch((err) => {
setIsLoading(false);
dispatch(
addNotification({
variant: 'danger',
title: 'Could not list access requests',
description: err.message,
})
);
});
};
const debouncedAccountFilter = useDebounce(accountFilter, 400);
React.useEffect(() => {
fetchAccessRequests();
}, [
debouncedAccountFilter,
statusSelections,
activeSortIndex,
activeSortDirection,
perPage,
page,
]);
// Modal actions
const [openModal, setOpenModal] = React.useState({ type: null });
const onModalClose = (isChanged) => {
setOpenModal({ type: null });
if (isChanged) {
fetchAccessRequests();
}
};
const modals = (
<React.Fragment>
{openModal.type === 'cancel' && (
<CancelRequestModal
requestId={openModal.requestId}
onClose={onModalClose}
/>
)}
{['edit', 'create'].includes(openModal.type) && (
<EditRequestModal
variant={openModal.type}
requestId={openModal.requestId}
onClose={onModalClose}
/>
)}
</React.Fragment>
);
// Rendering
const createButton = isInternal && (
<Button variant="primary" onClick={() => setOpenModal({ type: 'create' })}>
Create request
</Button>
);
if (rows.length === 0 && !isLoading && !filtersDirty) {
return (
<Bullseye style={{ height: 'auto' }} className="pf-u-mt-lg">
<EmptyState variant="large">
<EmptyStateIcon icon={PlusCircleIcon} />
<Title headingLevel="h3" size="lg">
{isInternal ? 'No access requests' : 'You have no access requests'}
</Title>
<EmptyStateBody>
{isInternal
? 'Click the button below to create an access request.'
: 'You have no pending Red Hat access requests.'}
</EmptyStateBody>
{createButton}
</EmptyState>
{modals}
</Bullseye>
);
}
const selectLabelId = 'filter-status';
const selectPlaceholder = `Filter by ${uncapitalize(
columns[columns.length - 1]
)}`;
const clearFiltersButton = (
<Button
variant="link"
onClick={() => {
setStatusSelections([]);
setAccountFilter('');
setPage(1);
}}
>
Clear filters
</Button>
);
const toolbar = (
<Toolbar id="access-requests-table-toolbar">
<ToolbarContent>
<ToolbarItem>
<InputGroup>
<Dropdown
isOpen={isDropdownOpen}
onSelect={(ev) => {
setIsDropdownOpen(false);
setFilterColumn(ev.target.value);
setIsSelectOpen(false);
setFiltersDirty(true);
}}
toggle={
<DropdownToggle
onToggle={(isOpen) => setIsDropdownOpen(isOpen)}
>
<FilterIcon /> {filterColumn}
</DropdownToggle>
}
// https://marvelapp.com/prototype/257je526/screen/74764732
dropdownItems={(isInternal ? [1, 5] : [6])
.map((i) => columns[i])
.map((colName) => (
// Filterable columns are RequestID, AccountID, and Status
<DropdownItem
key={colName}
value={colName}
component="button"
>
{capitalize(colName)}
</DropdownItem>
))}
/>
{['Status', 'Decision'].includes(filterColumn) && (
<React.Fragment>
<span id={selectLabelId} hidden>
{selectPlaceholder}
</span>
<Select
aria-labelledby={selectLabelId}
variant="checkbox"
aria-label="Select statuses"
onToggle={(isOpen) => setIsSelectOpen(isOpen)}
onSelect={(_ev, selection) => {
setFiltersDirty(true);
if (statusSelections.includes(selection)) {
setStatusSelections(
statusSelections.filter((s) => s !== selection)
);
} else {
setStatusSelections([...statusSelections, selection]);
}
setPage(1);
}}
isOpen={isSelectOpen}
selections={Array.from(statusSelections)}
isCheckboxSelectionBadgeHidden
placeholderText={selectPlaceholder}
>
{statuses.map((status) => (
<SelectOption key={status} value={status}>
{capitalize(status)}
</SelectOption>
))}
</Select>
</React.Fragment>
)}
{filterColumn === 'Account number' && (
<form
style={{ display: 'flex' }}
onSubmit={(ev) => ev.preventDefault()}
>
<TextInput
name={`${filterColumn}-filter`}
id={`${filterColumn}-filter`}
type="search"
iconVariant="search"
placeholder={`Filter by ${uncapitalize(filterColumn)}`}
aria-label={`${filterColumn} search input`}
value={accountFilter}
onChange={(val) => {
setAccountFilter(val), setFiltersDirty(true), setPage(1);
}}
/>
</form>
)}
</InputGroup>
</ToolbarItem>
<ToolbarItem>{createButton}</ToolbarItem>
<ToolbarItem variant="pagination" align={{ default: 'alignRight' }}>
<AccessRequestsPagination id="top" />
</ToolbarItem>
</ToolbarContent>
<ToolbarContent>
<ChipGroup categoryName="Status">
{statusSelections.map((status) => (
<Chip
key={status}
onClick={() => {
setStatusSelections(
statusSelections.filter((s) => s !== status)
);
setPage(1);
}}
>
{status}
</Chip>
))}
</ChipGroup>
{accountFilter && (
<ChipGroup categoryName="Account number">
<Chip
onClick={() => {
setAccountFilter(''), setPage(1);
}}
>
{accountFilter}
</Chip>
</ChipGroup>
)}
{hasFilters && clearFiltersButton}
</ToolbarContent>
</Toolbar>
);
function getColumnWidth(columnIndex) {
if (isInternal) {
return columnIndex === 0 ? 30 : 15;
}
return [0, 6].includes(columnIndex) ? 20 : 10;
}
const { url } = useRouteMatch();
const table = (
<TableComposable aria-label="Access requests table" variant="compact">
<Thead>
<Tr>
{columns.map((column, columnIndex) => (
<Th
key={columnIndex}
{...(!column.includes('name') &&
column !== 'Decision' && {
sort: {
sortBy: {
index: activeSortIndex,
direction: activeSortDirection,
},
onSort,
columnIndex,
},
})}
width={getColumnWidth(columnIndex)}
>
{column}
</Th>
))}
{isInternal && <Th />}
</Tr>
</Thead>
<Tbody>
{isLoading
? [...Array(rows.length || perPage).keys()].map((i) => (
<Tr key={i}>
{columns.map((name, j) => (
<Td key={j} dataLabel={name}>
<div
style={{ height: '30px' }}
className="ins-c-skeleton ins-c-skeleton__md"
>
{' '}
</div>
</Td>
))}
</Tr>
))
: rows.map((row, rowIndex) => (
<Tr key={rowIndex}>
<Td dataLabel={columns[0]}>
<Link to={`${url}${url.endsWith('/') ? '' : '/'}${row[0]}`}>
{row[0]}
</Link>
</Td>
<Td dataLabel={columns[1]}>{row[1]}</Td>
<Td dataLabel={columns[2]}>{row[2]}</Td>
<Td dataLabel={columns[3]}>{row[3]}</Td>
<Td dataLabel={columns[4]}>{row[4]}</Td>
{isInternal ? (
<Td dataLabel={columns[5]}>
<StatusLabel
requestId={row[0]}
status={row[5]}
onLabelClick={() => {
setStatusSelections([
...statusSelections.filter((s) => s !== status),
status,
]);
setPage(1);
}}
hideActions
/>
</Td>
) : (
<Td dataLabel={columns[5]}>{row[5]}</Td>
)}
{isInternal ? (
// Different actions based on status
<Td
actions={getInternalActions(row[5], row[0], setOpenModal)}
/>
) : (
<Td dataLabel={columns[6]}>
<StatusLabel requestId={row[0]} status={row[6]} />
</Td>
)}
</Tr>
))}
{rows.length === 0 && hasFilters && (
<Tr>
<Td colSpan={columns.length}>
<EmptyState variant="small">
<EmptyStateIcon icon={SearchIcon} />
<Title headingLevel="h2" size="lg">
No matching requests found
</Title>
<EmptyStateBody>
No results match the filter criteria. Remove all filters or
clear all filters to show results.
</EmptyStateBody>
{clearFiltersButton}
</EmptyState>
</Td>
</Tr>
)}
</Tbody>
</TableComposable>
);
return (
<React.Fragment>
{toolbar}
{table}
<AccessRequestsPagination id="bottom" />
{modals}
</React.Fragment>
);
}
Example #29
Source File: ClusterHeader.js From ocp-advisor-frontend with Apache License 2.0 | 4 votes |
ClusterHeader = ({ clusterId, clusterData, clusterInfo }) => {
const location = window.location;
const [isOpen, setIsOpen] = useState(false);
const intl = useIntl();
// subscribe to the cluster data query
const {
isUninitialized: isUninitializedCluster,
isFetching: isFetchingCluster,
data: cluster,
} = clusterData;
const {
isUninitialized: isUninitializedInfo,
isFetching: isFetchingInfo,
data: info,
} = clusterInfo;
const redirectOCM = (clusterId) => {
location.assign(
location.origin +
(location.pathname.includes('beta') ? `/beta` : '') +
`/openshift/details/${clusterId}`
);
};
const dropDownItems = [
<DropdownItem key="link" onClick={() => redirectOCM(clusterId)}>
<snap>{intl.formatMessage(messages.clusterDetailsRedirect)}</snap>
</DropdownItem>,
];
return (
<Grid id="cluster-header" md={12} hasGutter>
<GridItem span={8}>
<Title
size="2xl"
headingLevel="h1"
id="cluster-header-title"
ouiaId="cluster-name"
>
{isUninitializedInfo || isFetchingInfo ? (
<Skeleton size="sm" />
) : (
info?.display_name || clusterId
)}
</Title>
</GridItem>
<GridItem span={4} id="cluster-header-dropdown">
<Dropdown
position="right"
onSelect={() => setIsOpen(!isOpen)}
autoFocus={false}
isOpen={isOpen}
toggle={
<DropdownToggle
id="toggle-id-2"
onToggle={(isOpen) => setIsOpen(isOpen)}
>
{intl.formatMessage(messages.dropDownActionSingleCluster)}
</DropdownToggle>
}
dropdownItems={dropDownItems}
/>
</GridItem>
<GridItem>
<Stack>
<StackItem id="cluster-header-uuid">
<span>UUID:</span> <span>{clusterId}</span>
</StackItem>
<StackItem id="cluster-header-last-seen">
<span>{intl.formatMessage(messages.lastSeen)}: </span>
<span>
{isUninitializedCluster || isFetchingCluster ? (
<OneLineLoader />
) : cluster?.report?.meta?.last_checked_at ? (
<DateFormat
date={cluster?.report?.meta?.last_checked_at}
type="exact"
/>
) : (
intl.formatMessage(messages.unknown)
)}
</span>
</StackItem>
</Stack>
</GridItem>
</Grid>
);
}