@patternfly/react-core#StackItem JavaScript Examples
The following examples show how to use
@patternfly/react-core#StackItem.
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: EmptyStates.js From ocp-advisor-frontend with Apache License 2.0 | 6 votes |
ErrorState = () => {
const intl = useIntl();
return (
<MessageState
title={intl.formatMessage(messages.errorStateTitle)}
text={
<Stack>
<StackItem>{intl.formatMessage(messages.errorStateBody)}</StackItem>
<StackItem>
<DefaultErrorMessage />
</StackItem>
</Stack>
}
icon={ExclamationCircleIcon}
iconStyle={{ color: globalDangerColor100.value }}
/>
);
}
Example #2
Source File: LogNestedtable.js From sed-frontend with Apache License 2.0 | 6 votes |
LogNestedTable = ({ services, isInsights }) => {
return (
<Stack>
<StackItem>
<TextContent>
<Text component={TextVariants.h3}>State pushed to systems</Text>
</TextContent>
</StackItem>
<Table
aria-label="Active services Table"
className="sed-c-services__table"
cells={columns}
rows={[
{
noPadding: true,
cells: [
'Connected to Red Hat Insighsts',
isInsights ? 'on' : 'off',
],
},
...Object.entries(services).map(([key, value]) => [
rowMapper[key],
value === 'enabled' ? 'on' : 'off',
]),
]}
variant="compact"
>
<TableHeader />
<TableBody />
</Table>
</Stack>
);
}
Example #3
Source File: customPackage.js From edge-frontend with Apache License 2.0 | 5 votes |
CustomPackageLabel = () => {
const { getState, change } = useFormApi();
const addedRepos = getState()?.values?.['third-party-repositories'];
const initialRepos = getState()?.values?.['initial-custom-repositories'];
const customPackages = getState()?.values?.['custom-packages'];
const release = getState()?.values?.release;
const releaseName = release !== undefined ? releaseMapper[release] : '';
useEffect(() => {
change('validate-custom-repos', true);
change('show-custom-packages', true);
}, []);
return (
<>
<TextContent>
<Text>
Add packages from{' '}
<Popover
style={{ visibility: 'visible' }}
position="bottom"
headerContent="Custom Repositories"
bodyContent={
<Stack>
{addedRepos.map((repo) => (
<StackItem key={repo}>
<Text>{repo.name}</Text>
</StackItem>
))}
</Stack>
}
>
<Button variant="link" isInline>
{addedRepos.length} custom repositories
</Button>{' '}
to your
</Popover>
<b> {releaseName}</b> image.
</Text>
</TextContent>
{addedRepos.length === 0 && customPackages.length > 0
? showAlert('danger')
: checkRepoNameMismatch(initialRepos, addedRepos, customPackages)
? showAlert('warning')
: null}
</>
);
}
Example #4
Source File: ImageVersionDetail.js From edge-frontend with Apache License 2.0 | 5 votes |
ImageVersionDetail = ({ data, imageVersion }) => {
const history = useHistory();
const [isUpdateWizardOpen, setIsUpdateWizardOpen] = useState(false);
const [imageData, setImageData] = useState({});
useEffect(() => {
setImageData(data);
}, [data]);
const openUpdateWizard = () => {
history.push({
pathname: history.location.pathname,
search: new URLSearchParams({
update_image: true,
}).toString(),
});
setIsUpdateWizardOpen(true);
};
return (
<Fragment>
<PageHeader className="pf-m-light">
<Stack hasGutter>
<StackItem>
<DetailsHead
imageData={imageData}
imageVersion={imageVersion}
openUpdateWizard={openUpdateWizard}
/>
</StackItem>
</Stack>
<StackItem>
<Text>{data?.Description}</Text>
</StackItem>
</PageHeader>
<ImageDetailTabs imageData={imageData} imageVersion={imageVersion} />
{isUpdateWizardOpen && (
<Suspense
fallback={
<Bullseye>
<Spinner />
</Bullseye>
}
>
<UpdateImageWizard
navigateBack={() => {
history.push({ pathname: history.location.pathname });
setIsUpdateWizardOpen(false);
}}
updateimageVersionId={data?.ID}
/>
</Suspense>
)}
</Fragment>
);
}
Example #5
Source File: DeviceSummaryTile.js From edge-frontend with Apache License 2.0 | 5 votes |
DeviceSummaryTileBase = ({ orphaned, active, noReports, neverReported, }) => ( <Card className="tiles-card"> <CardTitle>Device summary</CardTitle> <CardBody> <Grid> <GridItem span={6}> <Stack hasGutter> <StackItem> <Button isDisabled isInline className="pf-u-pr-md" variant="link"> {active} </Button>{' '} Active </StackItem> <StackItem> <Button isDisabled isInline className="pf-u-pr-md" variant="link"> {orphaned} </Button>{' '} Orphaned </StackItem> </Stack> </GridItem> <GridItem span={6}> <Stack hasGutter> <StackItem> <Button isDisabled isInline className="pf-u-pr-md" variant="link"> {noReports} </Button> Stale </StackItem> <StackItem> <Button isDisabled isInline className="pf-u-pr-md" variant="link"> {neverReported} </Button> Registered but never reported </StackItem> </Stack> </GridItem> </Grid> </CardBody> </Card> )
Example #6
Source File: TasksPage.js From tasks-frontend with Apache License 2.0 | 5 votes |
TasksPage = ({ tab }) => {
const history = useHistory();
const [tabIndex, setTab] = useState(tab);
const [runTaskModalOpened, setRunTaskModalOpened] = useState(false);
const [activeTask, setActiveTask] = useState({});
const [error, setError] = useState();
useEffect(() => {
if (tab === 0) {
history.push('available');
}
}, []);
const updateTab = (event, index) => {
history.push(index ? 'executed' : 'available');
setTab(index);
};
const openTaskModal = async (slug) => {
const task = await fetchAvailableTask(slug);
if (task?.response?.status && task?.response?.status !== 200) {
setError(task);
dispatchNotification({
variant: 'danger',
title: 'Error',
description: task.message,
dismissable: true,
});
} else {
setActiveTask(task);
}
setRunTaskModalOpened(true);
};
return (
<React.Fragment>
<RunTaskModal
error={error}
task={activeTask}
isOpen={runTaskModalOpened}
setModalOpened={setRunTaskModalOpened}
/>
<PageHeader>
<FlexibleFlex
flexContents={TASKS_PAGE_HEADER}
flexProps={TASKS_PAGE_HEADER_FLEX_PROPS}
/>
</PageHeader>
<TasksTabs
className="tabs-background"
tabIndex={tabIndex}
updateTab={updateTab}
tabsList={TASKS_PAGE_TABS}
/>
<Main>
<Stack hasGutter>
<StackItem>
{tabIndex === 0 ? (
<AvailableTasks openTaskModal={openTaskModal} />
) : (
<CompletedTasksTable />
)}
</StackItem>
</Stack>
</Main>
</React.Fragment>
);
}
Example #7
Source File: Details.js From content-preview with Apache License 2.0 | 4 votes |
Details = ({
match,
fetchContentDetails,
details,
fetchContentDetailsHits,
contentDetailsHits
}) => {
const [selectedListItem, setSelectedListItem] = useState(0);
const capitalize = (string) => string[0].toUpperCase() + string.substring(1);
const [expanded, setExpanded] = useState(true);
const pyFilter = (data) => {
const keysToInclude = Object.keys(data).filter(
(key) => !key.includes('__')
);
const arrayObj = keysToInclude.map((key) => ({ [key]: data[key] }));
return Object.assign({}, ...arrayObj);
};
const selectedPyData =
selectedListItem >= 1 && pyFilter(contentDetailsHits[selectedListItem - 1]);
const detailHref = `https://access.redhat.com/node/${details.node_id}`;
const [freeStyle, setFreeStyle] = useState('');
const [freeStyleValidated, setFreeStyleValidated] = useState('default');
const [validFreeStyle, setValidFreeStyle] = useState('');
const [helperText, setHelperText] = useState('Please enter valid JSON');
const [kbaDetailsData, setLbaDetailsData] = useState({});
const [kbaLoading, setKbaLoading] = useState(true);
const freeStyleChange = (input) => {
let isValid;
const parser = (input) => {
try {
return JSON.parse(input);
} catch (error) {
return false;
}
};
if (input.length > 0) {
const validInput = parser(input);
if (validInput) {
isValid = 'success';
setValidFreeStyle(validInput);
setHelperText('Valid JSON! ?');
} else {
isValid = 'error';
setValidFreeStyle('');
}
} else {
isValid = 'default';
setValidFreeStyle('');
setHelperText('Please enter valid JSON');
}
setFreeStyleValidated(isValid);
setFreeStyle(input);
};
const severityLabelColor = (severity) =>
severity === 'ERROR'
? 'red'
: severity === 'WARN'
? 'orange'
: severity === 'INFO'
? 'purple'
: 'blue';
const fetchKbaDetails = async (kbaId) => {
try {
const kbaDetailsFetch = (
await API.get(
`https://access.redhat.com/hydra/rest/search/kcs?q=id:(${kbaId})&fl=view_uri,id,publishedTitle&rows=1&redhat_client=$ADVISOR`,
{},
{ credentials: 'include' }
)
).data.response.docs;
setLbaDetailsData(kbaDetailsFetch[0]);
setKbaLoading(false);
} catch (error) {
console.error(error, 'KBA fetch failed.');
}
};
const ruleDescription = (data, isGeneric) =>
typeof data === 'string' &&
Boolean(data) && (
<span className={isGeneric && 'genericOverride'}>
<Markdown rehypePlugins={[rehypeRaw, rehypeSanitize]}>{data}</Markdown>
</span>
);
useEffect(() => {
const detailName = { name: match.params.recDetail };
fetchContentDetails(detailName);
fetchContentDetailsHits(detailName);
fetchKbaDetails(details.node_id);
}, [
fetchContentDetails,
match.params.recDetail,
fetchContentDetailsHits,
details.node_id
]);
return (
<Page
breadcrumb={
<Breadcrumb>
<BreadcrumbItem>
<Link to="/preview">Content Preview</Link>
</BreadcrumbItem>
<BreadcrumbHeading to="#">{`${match.params.recDetail}`}</BreadcrumbHeading>
</Breadcrumb>
}
>
<PageHeader>
<Flex justifyContent={{ default: 'justifyContentSpaceBetween' }}>
<PageHeaderTitle
title={
<>
{details.rule_id || 'loading...'}{' '}
{details.status !== undefined && (
<Label color={details.status === 'active' ? 'green' : 'red'}>
{capitalize(details.status)}
</Label>
)}{' '}
</>
}
/>
<Toolbar>
<HostSelector />
</Toolbar>
</Flex>
</PageHeader>
<PageSection>
<Grid hasGutter>
<GridItem span={6}>
<Stack hasGutter>
<Card>
<CardBody>
<ExpandableSection
toggleText={details.description}
onToggle={() => setExpanded(!expanded)}
isExpanded={expanded}
>
<Stack hasGutter>
<StackItem>
<p>
{`Publish Date: ${details.publish_date} | `}
{details.node_id ? (
<a href={detailHref}>{detailHref}</a>
) : (
<Label variant="outline" color="gray">
No node_id present
</Label>
)}
</p>
{(details.reboot_required ||
details.category ||
details.severity) && (
<LabelGroup>
{details.reboot_required && (
<Label variant="outline" color="gray">
Reboot required
</Label>
)}
{details.category && (
<Label variant="outline" color="gray">
{details.category}
</Label>
)}
{details.severity && (
<Label
variant="outline"
color={severityLabelColor(details.severity)}
>
{details.severity}
</Label>
)}
</LabelGroup>
)}
</StackItem>
<StackItem>
<Stack hasGutter>
<StackItem>
<strong>Name:</strong>
{ruleDescription(details.name)}
</StackItem>
<StackItem>
<strong>Summary:</strong>
{ruleDescription(details.summary)}
</StackItem>
<StackItem>
<strong>Generic:</strong>
{ruleDescription(details.generic, true)}
</StackItem>
</Stack>
</StackItem>
<StackItem>
<Form>
<FormGroup
label="Free Style JSON input:"
type="string"
helperText={helperText}
helperTextInvalid="Not valid JSON"
fieldId="selection"
validated={freeStyleValidated}
>
<TextArea
value={freeStyle}
onChange={freeStyleChange}
isRequired
validated={freeStyleValidated}
aria-label="free style JSON input"
/>
</FormGroup>
</Form>
</StackItem>
</Stack>
</ExpandableSection>
</CardBody>
</Card>
<DataList
className="pyDataList"
aria-label="selectable data list example"
selectedDataListItemId={selectedListItem}
onSelectDataListItem={(id) =>
id !== selectedListItem
? setSelectedListItem(id)
: setSelectedListItem(0)
}
>
{contentDetailsHits.map((item, key) => (
<DataListItem
aria-labelledby="selectable-action-item1"
key={key + 1}
id={key + 1}
>
<DataListItemRow className="overFlow">
<DataListItemCells
dataListCells={[
<DataListCell key="primary content">
<Split hasGutter>
<SplitItem>
<b>{item.__name}</b>
</SplitItem>
<SplitItem>
<Label color="blue">{item.__source}</Label>
</SplitItem>
</Split>
<h5>{item.__date}</h5>
<pre>{JSON.stringify(pyFilter(item), null, 2)}</pre>
</DataListCell>
]}
/>
</DataListItemRow>
</DataListItem>
))}
</DataList>
</Stack>
</GridItem>
<GridItem span={6}>
<ReportDetails
report={{
...details,
rule: details,
...(selectedPyData && { details: selectedPyData }),
...(validFreeStyle && { details: validFreeStyle }),
resolution: details.resolution
}}
kbaDetail={kbaDetailsData}
kbaLoading={kbaLoading}
/>
</GridItem>
</Grid>
</PageSection>
</Page>
);
}
Example #8
Source File: index.js From dbaas-ui with Apache License 2.0 | 4 votes |
HomePage = () => {
return (
<React.Fragment>
<PageHeader className="dbaas-home-page__header pf-u-p-2xl">
<Grid>
<GridItem sm={12} md={6}>
<Title size="2xl" headingLevel="h1">
Get started with Red Hat OpenShift Database Access
</Title>
<Stack hasGutter>
<StackItem>
<TextContent>
<Text size="lg" className="dbaas-home-page__subtitle">
Add-on service for managed OpenShift
</Text>
<Text>
Easily discover, consume, monitor, and manage databases as a
service on the managed OpenShift Platform. OpenShift
database access helps accelerate your development for
applications that use MongoDB Atlas, Crunchy Bridge and
CockroachDB managed database services.
</Text>
</TextContent>
</StackItem>
<StackItem>
<Button
iconPosition="right"
icon={<ExternalLinkAltIcon />}
component="a"
target="_blank"
variant="secondary"
href="https://access.redhat.com/documentation/en-us/red_hat_openshift_database_access/1/html-single/quick_start_guide/index"
>
Get Started with OpenShift Database Access
</Button>
</StackItem>
</Stack>
</GridItem>
</Grid>
</PageHeader>
<Main className="pf-u-pt-xl pf-u-pb-xl pf-u-pl-2xl pf-u-pr-2xl">
<Title className="pf-u-mb-lg" headingLevel="h2" size="xl">
Demo of OpenShift Database Access
</Title>
<Stack hasGutter>
<StackItem>
<Grid hasGutter>
<GridItem md={6} sm={12}>
<Stack hasGutter>
<StackItem>
<TextContent>
<Text>
<b>For database admins:</b> in this video you’ll learn
how to set up a cloud database service connection on
your OpenShift cluster for self-service consumption by
application developers.
</Text>
</TextContent>
</StackItem>
<StackItem>
<Button
iconPosition="right"
icon={<ExternalLinkAltIcon />}
target="_blank"
component="a"
variant="secondary"
href="https://youtu.be/vDrh3SnciL0"
>
View the demo
</Button>
</StackItem>
</Stack>
</GridItem>
<GridItem md={6} sm={12}>
<iframe
style={{ width: '100%', height: '315px' }}
width="560"
height="315"
src="https://www.youtube.com/embed/vDrh3SnciL0"
title="YouTube video player"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
></iframe>
</GridItem>
</Grid>
</StackItem>
<StackItem>
<Grid hasGutter>
<GridItem md={6} sm={12}>
<Stack hasGutter>
<StackItem>
<TextContent>
<Text>
<b>For application developers:</b> in this video, you’ll
learn how to quickly and easily connect your application
to a cloud database service on your OpenShift cluster.
</Text>
</TextContent>
</StackItem>
<StackItem>
<Button
iconPosition="right"
icon={<ExternalLinkAltIcon />}
target="_blank"
component="a"
variant="secondary"
href="https://youtu.be/qWaAwhxwjWs"
>
View the demo
</Button>
</StackItem>
</Stack>
</GridItem>
<GridItem md={6} sm={12}>
<iframe
style={{ width: '100%', height: '315px' }}
width="560"
height="315"
src="https://www.youtube.com/embed/qWaAwhxwjWs"
title="YouTube video player"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
></iframe>
</GridItem>
</Grid>
</StackItem>
</Stack>
</Main>
</React.Fragment>
);
}
Example #9
Source File: ImageDetail.js From edge-frontend with Apache License 2.0 | 4 votes |
ImageDetail = () => {
const { imageId, imageVersionId } = useParams();
const history = useHistory();
const [updateWizard, setUpdateWizard] = useState({
isOpen: false,
updateId: null,
});
const [imageVersion, setImageVersion] = useState(null);
const [response, fetchImageSetDetails] = useApi({
api: getImageSet,
id: imageId,
tableReload: true,
});
const { data, isLoading } = response;
const openUpdateWizard = (id) => {
history.push({
pathname: history.location.pathname,
search: new URLSearchParams({
update_image: true,
}).toString(),
});
setUpdateWizard((prevState) => ({
...prevState,
isOpen: !prevState.isLoading,
updateId: id,
}));
};
useEffect(() => {
imageVersionId
? setImageVersion(
data?.Data?.images?.[
data?.Data?.images?.findIndex(
(image) => image?.image?.ID == imageVersionId
)
]
)
: setImageVersion(null);
}, [response, imageVersionId]);
useEffect(() => {
fetchImageSetDetails();
}, [imageId]);
return (
<Fragment>
<PageHeader className="pf-m-light">
<Stack hasGutter>
<StackItem>
<DetailsHead
imageData={response}
imageVersion={imageVersion}
openUpdateWizard={openUpdateWizard}
/>
</StackItem>
</Stack>
</PageHeader>
<ImageDetailTabs
imageData={response}
urlParam={imageId}
imageVersion={imageVersion}
openUpdateWizard={openUpdateWizard}
isLoading={isLoading}
/>
{updateWizard.isOpen && (
<Suspense
fallback={
<Bullseye>
<Spinner />
</Bullseye>
}
>
<UpdateImageWizard
navigateBack={() => {
history.push({ pathname: history.location.pathname });
setUpdateWizard((prevState) => ({ ...prevState, isOpen: false }));
}}
updateImageID={updateWizard.updateId}
/>
</Suspense>
)}
</Fragment>
);
}
Example #10
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>
);
}
Example #11
Source File: Services.js From sed-frontend with Apache License 2.0 | 4 votes |
Services = ({
defaults,
setConfirmChangesOpen,
onChange,
isEditing,
setIsEditing,
}) => {
const initState = {
enableCloudConnector: {
value: defaults.enableCloudConnector,
isDisabled: false,
},
useOpenSCAP: { value: defaults.useOpenSCAP, isDisabled: false },
};
const [formState, setFormState] = useState(initState);
const [madeChanges, setMadeChanges] = useState(false);
const { hasAccess, isLoading } = usePermissions(
'',
[
'config-manager:activation_keys:*',
'config-manager:state:read',
'config-manager:state:write',
'config-manager:state-changes:read',
'inventory:*:read',
'playbook-dispatcher:run:read',
],
false,
true
);
const cancelEditing = () => {
setFormState(initState);
setIsEditing(false);
};
useEffect(() => {
setMadeChanges(
formState.useOpenSCAP.value !== defaults.useOpenSCAP ||
formState.enableCloudConnector.value != defaults.enableCloudConnector
);
onChange({
useOpenSCAP: formState.useOpenSCAP.value,
enableCloudConnector: formState.enableCloudConnector.value,
});
}, [formState]);
const getStatusIcon = (row) => {
if (formState[row.id].value) {
return (
<Flex style={{ color: 'var(--pf-global--success-color--200)' }}>
<FlexItem spacer={{ default: 'spacerXs' }}>
<CheckCircleIcon />
</FlexItem>
<FlexItem className="status">
<b>Enabled</b>
</FlexItem>
</Flex>
);
}
return (
<Flex style={{ color: 'var(--pf-global--default-color--300)' }}>
<FlexItem spacer={{ default: 'spacerXs' }}>
<BanIcon />
</FlexItem>
<FlexItem className="status">
<b>Disabled</b>
</FlexItem>
</Flex>
);
};
return (
<Stack hasGutter className="pf-u-p-md">
<StackItem>
<Toolbar id="toolbar-items">
<ToolbarContent>
{!isEditing && (
<ToolbarItem>
{!hasAccess ? (
<Tooltip
content={
<div>
To perform this action, you must be granted the
"System Administrator" role by your
Organization Administrator in your Setting's User
Access area.
</div>
}
>
{changeSettingsButton(isLoading, hasAccess, setIsEditing)}
</Tooltip>
) : (
changeSettingsButton(isLoading, hasAccess, setIsEditing)
)}
</ToolbarItem>
)}
{isEditing && (
<>
<ToolbarItem>
<Button
ouiaId="primary-save-button"
onClick={() => setConfirmChangesOpen(true)}
isDisabled={!madeChanges}
>
Save changes
</Button>
</ToolbarItem>
<ToolbarItem>
<Button
ouiaId="secondary-cancel-button"
onClick={() => cancelEditing()}
variant="secondary"
>
Cancel
</Button>
</ToolbarItem>
<ToolbarItem>
<Alert
variant="info"
isInline
isPlain
title="Changes will affect all systems connected with Red Hat connector"
/>
</ToolbarItem>
</>
)}
</ToolbarContent>
</Toolbar>
</StackItem>
<StackItem>
<TableComposable aria-label="Settings table">
<Thead>
<Tr>
<Th>Permission</Th>
<Th>Status</Th>
</Tr>
</Thead>
<Tbody>
{permissions.map((row) => (
<Tr key={row.name}>
<Td
dataLabel="Permission"
width={80}
style={row.secondary && { paddingLeft: 70, fontSize: 14 }}
>
<Stack>
<StackItem>
<Flex>
<FlexItem>
<b>{row.name}</b>
</FlexItem>
{row.additionalInfo && (
<FlexItem
style={{ color: 'var(--pf-global--Color--100)' }}
>
<i>{row.additionalInfo}</i>
</FlexItem>
)}
</Flex>
</StackItem>
<StackItem style={{ fontSize: 14 }}>
{row.description}
</StackItem>
{row.links && (
<StackItem className="stack-item">
<Flex>
{row.links.map((link) => (
<FlexItem key={link.name}>
<a
href={link.link}
target="_blank"
rel="noopener noreferrer"
>
{link.name}
<ExternalLinkAltIcon className="pf-u-ml-sm" />
</a>
</FlexItem>
))}
</Flex>
</StackItem>
)}
</Stack>
</Td>
{!isEditing && <Td dataLabel="Status">{getStatusIcon(row)}</Td>}
{isEditing && (
<Td dataLabel="Status">
<ToggleGroup aria-label="Default with single selectable">
<ToggleGroupItem
text="Enabled"
isSelected={formState[row.id].value}
onChange={() =>
setFormState({
...formState,
[row.id]: { ...formState[row.id], value: true },
})
}
isDisabled={formState[row.id].isDisabled}
/>
<ToggleGroupItem
text="Disabled"
isSelected={!formState[row.id].value}
onChange={() =>
setFormState({
...formState,
[row.id]: { ...formState[row.id], value: false },
})
}
isDisabled={formState[row.id].isDisabled}
/>
</ToggleGroup>
</Td>
)}
</Tr>
))}
</Tbody>
</TableComposable>
</StackItem>
</Stack>
);
}
Example #12
Source File: index.js From sed-frontend with Apache License 2.0 | 4 votes |
SamplePage = () => {
const history = useHistory();
const { getRegistry } = useContext(RegistryContext);
const [confirmChangesOpen, setConfirmChangesOpen] = useState(false);
const [madeChanges, setMadeChanges] = useState(false);
const [isEditing, setIsEditing] = useState(false);
const dataRef = useRef();
const dispatch = useDispatch();
const activeStateLoaded = useSelector(
({ activeStateReducer }) => activeStateReducer?.loaded
);
const { useOpenSCAP, enableCloudConnector, hasInsights } = useSelector(
({ activeStateReducer }) => ({
useOpenSCAP: activeStateReducer?.values?.useOpenSCAP,
enableCloudConnector: activeStateReducer?.values?.enableCloudConnector,
hasInsights: activeStateReducer?.values?.hasInsights,
}),
shallowEqual
);
const { systemsCount } = useSelector(
({ connectedSystemsReducer }) => ({
systemsLoaded: connectedSystemsReducer?.loaded,
systemsCount: connectedSystemsReducer?.total,
}),
shallowEqual
);
useEffect(() => {
getRegistry().register({
activeStateReducer,
logReducer,
connectedSystemsReducer,
});
dispatch(fetchCurrState());
dispatch(fetchConnectedHosts());
}, [getRegistry]);
useEffect(() => {
insights?.chrome?.appAction?.('cloud-connector-dashboard');
}, []);
return (
<React.Fragment>
<Route
exact
path={paths.logModal}
render={() => (
<Suspense
fallback={
<Bullseye>
<Spinner />
</Bullseye>
}
>
<ConnectLog />
</Suspense>
)}
/>
<PageHeader className="page-header">
<Split hasGutter className="page-title">
<SplitItem isFilled>
<Flex>
<FlexItem spacer={{ default: 'spacerSm' }}>
<PageHeaderTitle title="Remote Host Configuration Manager" />
</FlexItem>
<FlexItem>
<AboutRemoteHostConfigPopover />
</FlexItem>
</Flex>
</SplitItem>
<SplitItem>
<Button onClick={() => history.push(paths.logModal)} variant="link">
View log
</Button>
</SplitItem>
</Split>
<Stack hasGutter>
<StackItem>
Selections here affect Red Hat Enterprise Linux (RHEL) systems
connected to Red Hat with remote host configuration (rhc). Upon
saving changes, Ansible Playbooks are automatically pushed to
connected systems to update the configuration of the connection to
Red Hat.
</StackItem>
<StackItem>
<a
target="_blank"
rel="noopener noreferrer"
href={
'https://access.redhat.com/documentation/en-us/red_hat_insights/2022/html-single/red_hat_connector_configuration_guide/index'
}
>
Connecting with Red Hat
{<ExternalLinkAltIcon className="pf-u-ml-sm" />}
</a>
</StackItem>
</Stack>
</PageHeader>
<Page>
<div className="dashboard__content">
{activeStateLoaded ||
(useOpenSCAP !== undefined && enableCloudConnector !== undefined) ? (
<Services
madeChanges={madeChanges}
setConfirmChangesOpen={setConfirmChangesOpen}
setMadeChanges={setMadeChanges}
setIsEditing={setIsEditing}
isEditing={isEditing}
defaults={{
useOpenSCAP,
enableCloudConnector,
hasInsights,
}}
onChange={(data) => {
dataRef.current = data;
}}
/>
) : (
<Bullseye>
<Spinner className="pf-u-p-lg" size="xl" />
</Bullseye>
)}
</div>
</Page>
<ConfirmChangesModal
isOpen={confirmChangesOpen}
handleCancel={() => setConfirmChangesOpen(false)}
systemsCount={systemsCount}
data={dataRef.current}
handleConfirm={() => {
setConfirmChangesOpen(false);
(async () => {
const saveAction = saveCurrState(dataRef.current);
dispatch(saveAction);
await saveAction.payload;
dispatch(
addNotification({
variant: 'success',
title: 'Changes saved',
description:
'Your service enablement changes were applied to connected systems',
})
);
setMadeChanges(false);
setIsEditing(false);
})();
}}
/>
</React.Fragment>
);
}
Example #13
Source File: Email.js From user-preferences-frontend with Apache License 2.0 | 4 votes |
Email = () => {
const dispatch = useDispatch();
const [emailConfig, setEmailConfig] = useState({});
const isLoaded = useLoaded(async () => {
await insights.chrome.auth.getUser();
register(emailPreferences);
setEmailConfig(await calculateEmailConfig(config, dispatch));
});
const store = useSelector(({ emailPreferences }) => emailPreferences);
const saveValues = async ({ unsubscribe, ...values }) => {
const promises = Object.entries(emailConfig)
.filter(([, { isVisible }]) => isVisible === true)
.map(([application, { localFile, schema, url, apiName }]) => {
if (
!localFile &&
!schema &&
store?.[application]?.schema &&
Object.keys(store?.[application]?.schema).length > 0
) {
const action = saveEmailValues({ application, values, url, apiName });
dispatch(action);
return {
promise: action.payload,
meta: action.meta,
};
}
})
.filter(Boolean);
const { success, error } = await distributeSuccessError(promises);
dispatchMessages(dispatch, success, error);
};
const calculateSection = (key, schema) => {
return getSection(key, schema, store?.[key], (isVisible) => {
const { ...config } = emailConfig;
if (isVisible === false) {
delete config[key];
} else {
config[key] = {
...config[key],
isVisible,
};
}
setEmailConfig(config);
});
};
return (
<React.Fragment>
<PageHeader>
<PageHeaderTitle title="Email preferences" />
</PageHeader>
<Main className="pref-email">
<Stack hasGutter>
<StackItem>
<YourInformation />
</StackItem>
<StackItem>
<Card ouiaId="user-pref-email-subscriptions-card">
<CardHeader className="pf-u-pb-0">
<TextContent>
<Text component={TextVariants.h2}>Email subscriptions</Text>
<Text component={TextVariants.p}>
Select the emails you want to receive.
</Text>
</TextContent>
</CardHeader>
<CardBody className="pref-email_form">
{isLoaded ? (
<FormRender
componentMapper={{
...componentMapper,
[DESCRIPTIVE_CHECKBOX]: DescriptiveCheckbox,
[LOADER]: Loader,
[DATA_LIST]: DataListLayout,
}}
FormTemplate={(props) => (
<FormTemplate {...props} FormButtons={FormButtons} />
)}
schema={{
fields: [
{
name: 'email-preferences',
component: DATA_LIST,
sections: Object.entries(emailConfig).map(
([key, schema]) => calculateSection(key, schema)
),
},
],
}}
onSubmit={saveValues}
/>
) : (
<Bullseye>
<Spinner />
</Bullseye>
)}
</CardBody>
</Card>
</StackItem>
</Stack>
</Main>
</React.Fragment>
);
}
Example #14
Source File: Notification.js From user-preferences-frontend with Apache License 2.0 | 4 votes |
Notification = () => {
const { bundleName } = useParams();
const navigateTo = useChromePush();
const dispatch = useDispatch();
const store = useSelector(
({ notificationPreferences }) => notificationPreferences
);
const bundleDisplayTitle = notificationConfigForBundle(bundleName)?.title;
useEffect(() => {
register(notificationPreferences);
}, []);
useEffect(() => {
(async () => {
await insights.chrome.auth.getUser();
if (bundleName) {
dispatch(getNotificationSchema({ bundleName }));
}
})();
}, [bundleName]);
const { isLoaded, schema } = useMemo(() => {
if (store?.loaded) {
const schema = { ...store.schema };
if (schema.fields) {
schema.fields = [...schema.fields];
schema.fields[0].sections = [...schema.fields[0].sections];
schema.fields[0].sections.push({
fields: unsubscribe,
});
} else {
schema.fields = [];
}
return {
isLoaded: true,
schema: schema,
};
}
return {
isLoaded: false,
schema: [],
};
}, [store]);
const saveValues = useCallback(
async ({ unsubscribe, ...values }) => {
const action = saveNotificationValues({ bundleName, values });
dispatch(action);
try {
await action.payload;
dispatch(
addNotification({
dismissable: false,
variant: 'success',
title: `Notification preferences successfully saved`,
})
);
} catch (e) {
dispatch(
addNotification({
dismissable: false,
variant: 'danger',
title: `Notification preferences unsuccessfully saved`,
})
);
}
},
[bundleName]
);
return (
<React.Fragment>
<PageHeader>
<Split>
<SplitItem isFilled>
<PageHeaderTitle
className="notif-page-header"
title={`My Notifications | ${bundleDisplayTitle}`}
/>
<StackItem>
This service allows you to opt-in and out of receiving
notifications. Your Organization Administrator has configured
which notifications you can or can not receive in their{' '}
<a
onClick={(e) =>
navigateTo(e, `/settings/notifications/${bundleName}`)
}
href={`/settings/notifications/${bundleName}`}
>
Settings
</a>
.
</StackItem>
</SplitItem>
</Split>
</PageHeader>
<Main className="pref-notification">
<Stack hasGutter>
<StackItem>
<Card ouiaId="user-pref-notification-subscriptions-card">
<CardHeader className="pf-u-pb-0"></CardHeader>
<CardBody className="pref-notification_form">
{isLoaded ? (
<FormRender
componentMapper={{
...componentMapper,
[DESCRIPTIVE_CHECKBOX]: DescriptiveCheckbox,
[LOADER]: Loader,
[DATA_LIST]: DataListLayout,
}}
FormTemplate={(props) => (
<FormTemplate {...props} FormButtons={FormButtons} />
)}
schema={schema}
onSubmit={saveValues}
/>
) : (
<Bullseye>
<Spinner />
</Bullseye>
)}
</CardBody>
</Card>
</StackItem>
</Stack>
</Main>
</React.Fragment>
);
}
Example #15
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 #16
Source File: AddressesDataList.js From cockpit-wicked with GNU General Public License v2.0 | 4 votes |
AddressesDataList = ({ addresses, updateAddresses, allowEmpty = true }) => {
const addAddress = () => {
const address = createAddressConfig();
const currentAddresses = [...addresses];
currentAddresses.push(address);
updateAddresses(currentAddresses);
};
const updateAddress = (id, field, value) => {
const nextAddresses = [...addresses];
const address = nextAddresses.find((addr) => addr.id == id);
address[field] = value;
// TODO: check if this do not generate not needed re-renders
updateAddresses(nextAddresses);
};
const deleteAddress = (id) => {
const nextAddresses = [...addresses];
const addressIdx = nextAddresses.findIndex((addr) => addr.id == id);
nextAddresses.splice(addressIdx, 1);
updateAddresses(nextAddresses);
};
const renderAddress = ({ id, local, label }) => {
const renderDeleteAction = () => {
if (!allowEmpty && addresses.length === 1) return null;
return (
<DataListAction>
<Button variant="secondory" className="btn-sm" onClick={() => deleteAddress(id)}>
<MinusIcon />
</Button>
</DataListAction>
);
};
const cells = [
<DataListCell key={`address-${id}-local`}>
<IPInput
defaultValue={local}
onChange={(value) => updateAddress(id, 'local', value)}
placeholder={_("Address")}
aria-label={_("Address")}
/>
</DataListCell>,
<DataListCell key={`address-${id}-label`}>
<TextInput
defaultValue={label}
onChange={(value) => updateAddress(id, 'label', value)}
placeholder={_("Label")}
aria-label={_("Label")}
/>
</DataListCell>
];
return (
<DataListItem key={`address-${id}`}>
<DataListItemRow>
<DataListItemCells dataListCells={cells} />
{ renderDeleteAction() }
</DataListItemRow>
</DataListItem>
);
};
return (
<Stack className="data-list-form" hasGutter>
<StackItem>
<Split hasGutter>
<SplitItem isFilled />
<SplitItem>
<Button variant="primary" className="btn-sm" onClick={() => addAddress() }>
<PlusIcon />
</Button>
</SplitItem>
</Split>
</StackItem>
<StackItem>
<DataList isCompact aria-label={_("Addresses data list")}>
{addresses.map((address) => renderAddress(address))}
</DataList>
</StackItem>
</Stack>
);
}