Skip to content

Commit

Permalink
implement no data and no permission screen
Browse files Browse the repository at this point in the history
  • Loading branch information
mgiota committed Mar 22, 2022
1 parent 316a086 commit 1699116
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 83 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { FormattedMessage } from '@kbn/i18n-react';
import React from 'react';
import { EuiButton, EuiEmptyPrompt, EuiLink, EuiButtonEmpty, EuiPageTemplate } from '@elastic/eui';

export function NoDataPrompt({
onCTAClicked,
documentationLink,
}: {
onCTAClicked: () => void;
documentationLink: string;
}) {
return (
<EuiPageTemplate
template="centeredContent"
pageContentProps={{
paddingSize: 'none',
role: null, // For passing a11y tests in EUI docs only
}}
>
<EuiEmptyPrompt
color="plain"
hasBorder={true}
data-test-subj="createFirstRuleEmptyPrompt"
title={
<h2>
<FormattedMessage
id="xpack.observability.rules.emptyPrompt.emptyTitle"
defaultMessage="Create your first Rule"
/>
</h2>
}
body={
<p>
<FormattedMessage
id="xpack.triggersActionsUI.components.emptyPrompt.emptyDesc"
defaultMessage="Rules allow you to receive alerts and automate custom actions when specific conditions are met."
/>
</p>
}
actions={[
<EuiButton
iconType="plusInCircle"
data-test-subj="createFirstRuleButton"
key="create-action"
fill
onClick={onCTAClicked}
>
<FormattedMessage
id="xpack.observability.rules.emptyPrompt.emptyButton"
defaultMessage="Create Rule"
/>
</EuiButton>,
<EuiButtonEmpty color="primary">
<EuiLink href={documentationLink} target="_blank">
Documentation
</EuiLink>
</EuiButtonEmpty>,
]}
/>
</EuiPageTemplate>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { FormattedMessage } from '@kbn/i18n-react';
import React from 'react';
import { EuiEmptyPrompt, EuiPageTemplate } from '@elastic/eui';

export function NoPermissionPrompt() {
return (
<EuiPageTemplate
template="centeredContent"
pageContentProps={{
paddingSize: 'none',
role: null, // For passing a11y tests in EUI docs only
}}
>
<EuiEmptyPrompt
color="plain"
hasBorder={true}
iconType="securityApp"
title={
<h1>
<FormattedMessage
id="xpack.observability.rules.noPermissionToCreateTitle"
defaultMessage="No permissions to create rules"
/>
</h1>
}
body={
<p data-test-subj="permissionDeniedMessage">
<FormattedMessage
id="xpack.observability.rules.noPermissionToCreateDescription"
defaultMessage="Contact your system administrator."
/>
</p>
}
/>
</EuiPageTemplate>
);
}
187 changes: 104 additions & 83 deletions x-pack/plugins/observability/public/pages/rules/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import { ExecutionStatus } from './components/execution_status';
import { LastRun } from './components/last_run';
import { EditRuleFlyout } from './components/edit_rule_flyout';
import { DeleteModalConfirmation } from './components/delete_modal_confirmation';
import { NoDataPrompt } from './components/prompts/noData_prompt';
import { NoPermissionPrompt } from './components/prompts/noPermission_prompt';
import {
deleteRules,
RuleTableItem,
Expand Down Expand Up @@ -78,6 +80,7 @@ export function RulesPage() {
application: { capabilities },
notifications: { toasts },
} = useKibana().services;
const documentationLink = docLinks.links.alerting.guide;
const ruleTypeRegistry = triggersActionsUi.ruleTypeRegistry;
const canExecuteActions = hasExecuteActionsCapability(capabilities);
const [page, setPage] = useState<Pagination>({ index: 0, size: DEFAULT_SEARCH_PAGE_SIZE });
Expand Down Expand Up @@ -243,6 +246,105 @@ export function RulesPage() {
[]
);

const getRulesTable = () => {
if (totalItemCount === 0 && !rulesState.isLoading) {
return authorizedToCreateAnyRules ? (
<NoDataPrompt
documentationLink={documentationLink}
onCTAClicked={() => setCreateRuleFlyoutVisibility(true)}
/>
) : (
<NoPermissionPrompt />
);
}
return (
<>
<EuiFlexGroup>
<EuiFlexItem>
<EuiFieldSearch
fullWidth
isClearable
data-test-subj="ruleSearchField"
onChange={(e) => {
setInputText(e.target.value);
if (e.target.value === '') {
setSearchText(e.target.value);
}
}}
onKeyUp={(e) => {
if (e.keyCode === ENTER_KEY) {
setSearchText(inputText);
}
}}
placeholder={SEARCH_PLACEHOLDER}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<LastResponseFilter
key="rule-lastResponse-filter"
selectedStatuses={ruleLastResponseFilter}
onChange={(ids: string[]) => setRuleLastResponseFilter(ids)}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
data-test-subj="refreshRulesButton"
iconType="refresh"
onClick={reload}
name="refresh"
color="primary"
>
<FormattedMessage
id="xpack.observability.rules.refreshRulesButtonLabel"
defaultMessage="Refresh"
/>
</EuiButton>
,
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiText size="s" color="subdued" data-test-subj="totalAlertsCount">
<FormattedMessage
id="xpack.observability.rules.totalItemsCountDescription"
defaultMessage="Showing: {pageSize} of {totalItemCount} Rules"
values={{
totalItemCount,
pageSize: rules.length,
}}
/>
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiAutoRefreshButton
isPaused={isPaused}
refreshInterval={refreshInterval}
onRefreshChange={onRefreshChange}
shortHand
/>
</EuiFlexItem>
</EuiFlexGroup>
<EuiHorizontalRule margin="xs" />
<EuiFlexGroup direction="column" gutterSize="s">
<EuiFlexItem>
<RulesTable
columns={getRulesTableColumns()}
rules={convertRulesToTableItems(rules, ruleTypeIndex, canExecuteActions)}
isLoading={rulesState.isLoading}
page={page}
totalItemCount={totalItemCount}
onPageChange={(index) => setPage(index)}
sort={sort}
onSortChange={(changedSort) => {
setSort(changedSort);
}}
/>
</EuiFlexItem>
</EuiFlexGroup>
</>
);
};

return (
<ObservabilityPageTemplate
pageHeader={{
Expand All @@ -267,7 +369,7 @@ export function RulesPage() {
</EuiButton>
),
<EuiButtonEmpty
href={docLinks.links.alerting.guide}
href={documentationLink}
target="_blank"
iconType="help"
data-test-subj="documentationLink"
Expand Down Expand Up @@ -303,88 +405,7 @@ export function RulesPage() {
setRulesState({ ...rulesState, isLoading });
}}
/>
<EuiFlexGroup>
<EuiFlexItem>
<EuiFieldSearch
fullWidth
isClearable
data-test-subj="ruleSearchField"
onChange={(e) => {
setInputText(e.target.value);
if (e.target.value === '') {
setSearchText(e.target.value);
}
}}
onKeyUp={(e) => {
if (e.keyCode === ENTER_KEY) {
setSearchText(inputText);
}
}}
placeholder={SEARCH_PLACEHOLDER}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<LastResponseFilter
key="rule-lastResponse-filter"
selectedStatuses={ruleLastResponseFilter}
onChange={(ids: string[]) => setRuleLastResponseFilter(ids)}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
data-test-subj="refreshRulesButton"
iconType="refresh"
onClick={reload}
name="refresh"
color="primary"
>
<FormattedMessage
id="xpack.observability.rules.refreshRulesButtonLabel"
defaultMessage="Refresh"
/>
</EuiButton>
,
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiText size="s" color="subdued" data-test-subj="totalAlertsCount">
<FormattedMessage
id="xpack.observability.rules.totalItemsCountDescription"
defaultMessage="Showing: {pageSize} of {totalItemCount} Rules"
values={{
totalItemCount,
pageSize: rules.length,
}}
/>
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiAutoRefreshButton
isPaused={isPaused}
refreshInterval={refreshInterval}
onRefreshChange={onRefreshChange}
shortHand
/>
</EuiFlexItem>
</EuiFlexGroup>
<EuiHorizontalRule margin="xs" />
<EuiFlexGroup direction="column" gutterSize="s">
<EuiFlexItem>
<RulesTable
columns={getRulesTableColumns()}
rules={convertRulesToTableItems(rules, ruleTypeIndex, canExecuteActions)}
isLoading={rulesState.isLoading}
page={page}
totalItemCount={totalItemCount}
onPageChange={(index) => setPage(index)}
sort={sort}
onSortChange={(changedSort) => {
setSort(changedSort);
}}
/>
</EuiFlexItem>
</EuiFlexGroup>
{getRulesTable()}
{error &&
toasts.addDanger({
title: error,
Expand Down

0 comments on commit 1699116

Please sign in to comment.