[Rollups] Migrate to new page layout (#102268) (#102975)

This commit is contained in:
Alison Goryachev 2021-06-22 19:37:08 -04:00 committed by GitHub
parent 51ce75a47f
commit 92c9a0e096
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 197 additions and 182 deletions

View file

@ -116,6 +116,7 @@ readonly links: {
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: string;
readonly rollupJobs: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;

File diff suppressed because one or more lines are too long

View file

@ -137,6 +137,7 @@ export class DocLinksService {
addData: `${KIBANA_DOCS}connect-to-elasticsearch.html`,
kibana: `${KIBANA_DOCS}index.html`,
upgradeAssistant: `${KIBANA_DOCS}upgrade-assistant.html`,
rollupJobs: `${KIBANA_DOCS}data-rollups.html`,
elasticsearch: {
docsBase: `${ELASTICSEARCH_DOCS}`,
asyncSearch: `${ELASTICSEARCH_DOCS}async-search-intro.html`,
@ -534,6 +535,7 @@ export interface DocLinksStart {
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: string;
readonly rollupJobs: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;

View file

@ -595,6 +595,7 @@ export interface DocLinksStart {
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: string;
readonly rollupJobs: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;

View file

@ -4,11 +4,3 @@
.rollupJobWizardStepActions {
align-items: flex-end; /* 1 */
}
/**
* 1. Ensure panel fills width of parent when search input yields no matching rollup jobs.
*/
.rollupJobsListPanel {
// sass-lint:disable-block no-important
flex-grow: 1 !important; /* 1 */
}

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React, { Component, Fragment } from 'react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { cloneDeep, debounce, first, mapValues } from 'lodash';
@ -18,11 +18,10 @@ import {
EuiCallOut,
EuiLoadingKibana,
EuiOverlayMask,
EuiPageContent,
EuiPageContentHeader,
EuiPageContentBody,
EuiPageHeader,
EuiSpacer,
EuiStepsHorizontal,
EuiTitle,
} from '@elastic/eui';
import {
@ -523,44 +522,46 @@ export class JobCreateUi extends Component {
}
saveErrorFeedback = (
<Fragment>
<>
<EuiSpacer />
<EuiCallOut title={message} icon="cross" color="danger">
{errorBody}
</EuiCallOut>
<EuiSpacer />
</Fragment>
</>
);
}
return (
<Fragment>
<EuiPageContent>
<EuiPageContentHeader>
<EuiTitle size="l">
<h1>
<FormattedMessage
id="xpack.rollupJobs.createTitle"
defaultMessage="Create rollup job"
/>
</h1>
</EuiTitle>
</EuiPageContentHeader>
<EuiPageContentBody restrictWidth style={{ width: '100%' }}>
<EuiPageHeader
bottomBorder
pageTitle={
<FormattedMessage
id="xpack.rollupJobs.createTitle"
defaultMessage="Create rollup job"
/>
}
/>
{saveErrorFeedback}
<EuiSpacer size="l" />
<EuiStepsHorizontal steps={this.getSteps()} />
<EuiStepsHorizontal steps={this.getSteps()} />
<EuiSpacer />
{saveErrorFeedback}
{this.renderCurrentStep()}
<EuiSpacer />
<EuiSpacer size="l" />
{this.renderCurrentStep()}
<EuiSpacer size="l" />
{this.renderNavigation()}
{this.renderNavigation()}
</EuiPageContent>
{savingFeedback}
</Fragment>
</EuiPageContentBody>
);
}

View file

@ -195,7 +195,7 @@ export class DetailPanel extends Component {
<EuiTextColor color="subdued">
<FormattedMessage
id="xpack.rollupJobs.detailPanel.loadingLabel"
defaultMessage="Loading rollup job..."
defaultMessage="Loading rollup job"
/>
</EuiTextColor>
</EuiText>

View file

@ -70,7 +70,7 @@ describe('<DetailPanel />', () => {
({ component, find, exists } = initTestBed({ isLoading: true }));
const loading = find('rollupJobDetailLoading');
expect(loading.length).toBeTruthy();
expect(loading.text()).toEqual('Loading rollup job...');
expect(loading.text()).toEqual('Loading rollup job');
// Make sure the title and the tabs are visible
expect(exists('detailPanelTabSelected')).toBeTruthy();

View file

@ -12,24 +12,19 @@ import { i18n } from '@kbn/i18n';
import {
EuiButton,
EuiButtonEmpty,
EuiEmptyPrompt,
EuiFlexGroup,
EuiFlexItem,
EuiLoadingSpinner,
EuiPageHeader,
EuiPageContent,
EuiPageContentHeader,
EuiPageContentHeaderSection,
EuiSpacer,
EuiText,
EuiTextColor,
EuiTitle,
EuiCallOut,
} from '@elastic/eui';
import { withKibana } from '../../../../../../../src/plugins/kibana_react/public';
import { extractQueryParams } from '../../../shared_imports';
import { extractQueryParams, SectionLoading } from '../../../shared_imports';
import { getRouterLinkProps, listBreadcrumb } from '../../services';
import { documentationLinks } from '../../services/documentation_links';
import { JobTable } from './job_table';
import { DetailPanel } from './detail_panel';
@ -87,38 +82,26 @@ export class JobListUi extends Component {
this.props.closeDetailPanel();
}
getHeaderSection() {
return (
<EuiPageContentHeaderSection data-test-subj="jobListPageHeader">
<EuiTitle size="l">
<h1>
<FormattedMessage id="xpack.rollupJobs.jobListTitle" defaultMessage="Rollup Jobs" />
</h1>
</EuiTitle>
</EuiPageContentHeaderSection>
);
}
renderNoPermission() {
const title = i18n.translate('xpack.rollupJobs.jobList.noPermissionTitle', {
defaultMessage: 'Permission error',
});
return (
<Fragment>
{this.getHeaderSection()}
<EuiSpacer size="m" />
<EuiCallOut
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="danger">
<EuiEmptyPrompt
data-test-subj="jobListNoPermission"
title={title}
color="warning"
iconType="help"
>
<FormattedMessage
id="xpack.rollupJobs.jobList.noPermissionText"
defaultMessage="You do not have permission to view or add rollup jobs."
/>
</EuiCallOut>
</Fragment>
iconType="alert"
title={<h1>{title}</h1>}
body={
<p>
<FormattedMessage
id="xpack.rollupJobs.jobList.noPermissionText"
defaultMessage="You do not have permission to view or add rollup jobs."
/>
</p>
}
/>
</EuiPageContent>
);
}
@ -130,101 +113,110 @@ export class JobListUi extends Component {
const title = i18n.translate('xpack.rollupJobs.jobList.loadingErrorTitle', {
defaultMessage: 'Error loading rollup jobs',
});
return (
<Fragment>
{this.getHeaderSection()}
<EuiSpacer size="m" />
<EuiCallOut data-test-subj="jobListError" title={title} color="danger" iconType="alert">
{statusCode} {errorString}
</EuiCallOut>
</Fragment>
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="danger">
<EuiEmptyPrompt
data-test-subj="jobListError"
iconType="alert"
title={<h1>{title}</h1>}
body={
<p>
{statusCode} {errorString}
</p>
}
/>
</EuiPageContent>
);
}
renderEmpty() {
return (
<EuiEmptyPrompt
data-test-subj="jobListEmptyPrompt"
iconType="indexRollupApp"
title={
<h1>
<FormattedMessage
id="xpack.rollupJobs.jobList.emptyPromptTitle"
defaultMessage="Create your first rollup job"
/>
</h1>
}
body={
<Fragment>
<p>
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="subdued">
<EuiEmptyPrompt
data-test-subj="jobListEmptyPrompt"
iconType="indexRollupApp"
title={
<h1>
<FormattedMessage
id="xpack.rollupJobs.jobList.emptyPromptDescription"
defaultMessage="Rollup jobs summarize and store historical data in a smaller index
for future analysis."
id="xpack.rollupJobs.jobList.emptyPromptTitle"
defaultMessage="Create your first rollup job"
/>
</p>
</Fragment>
}
actions={
<EuiButton
data-test-subj="createRollupJobButton"
{...getRouterLinkProps(`/create`)}
fill
iconType="plusInCircle"
>
<FormattedMessage
id="xpack.rollupJobs.jobList.emptyPrompt.createButtonLabel"
defaultMessage="Create rollup job"
/>
</EuiButton>
}
/>
</h1>
}
body={
<Fragment>
<p>
<FormattedMessage
id="xpack.rollupJobs.jobList.emptyPromptDescription"
defaultMessage="Rollup jobs summarize and store historical data in a smaller index
for future analysis."
/>
</p>
</Fragment>
}
actions={
<EuiButton
data-test-subj="createRollupJobButton"
{...getRouterLinkProps('/create')}
fill
iconType="plusInCircle"
>
<FormattedMessage
id="xpack.rollupJobs.jobList.emptyPrompt.createButtonLabel"
defaultMessage="Create rollup job"
/>
</EuiButton>
}
/>
</EuiPageContent>
);
}
renderLoading() {
return (
<EuiFlexGroup justifyContent="flexStart" alignItems="center" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiLoadingSpinner size="m" />
</EuiFlexItem>
<EuiFlexItem grow={false} data-test-subj="jobListLoading">
<EuiText>
<EuiTextColor color="subdued">
<FormattedMessage
id="xpack.rollupJobs.jobList.loadingTitle"
defaultMessage="Loading rollup jobs..."
/>
</EuiTextColor>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="subdued">
<SectionLoading>
<FormattedMessage
id="xpack.rollupJobs.jobList.loadingTitle"
defaultMessage="Loading rollup jobs…"
/>
</SectionLoading>
</EuiPageContent>
);
}
renderList() {
const { isLoading } = this.props;
return (
<Fragment>
<EuiPageContentHeader>
{this.getHeaderSection()}
<EuiPageContentHeaderSection>
<EuiButton fill {...getRouterLinkProps(`/create`)}>
<>
<EuiPageHeader
bottomBorder
pageTitle={
<span data-test-subj="jobListPageHeader">
<FormattedMessage id="xpack.rollupJobs.jobListTitle" defaultMessage="Rollup Jobs" />
</span>
}
rightSideItems={[
<EuiButtonEmpty
href={documentationLinks.rollupJobs}
target="_blank"
iconType="help"
data-test-subj="documentationLink"
>
<FormattedMessage
id="xpack.rollupJobs.jobList.createButtonLabel"
defaultMessage="Create rollup job"
id="xpack.rollupJobs.rollupJobsDocsLinkText"
defaultMessage="Rollup Jobs docs"
/>
</EuiButton>
</EuiPageContentHeaderSection>
</EuiPageContentHeader>
</EuiButtonEmpty>,
]}
/>
{isLoading ? this.renderLoading() : <JobTable />}
<EuiSpacer size="l" />
<JobTable />
<DetailPanel />
</Fragment>
</>
);
}
@ -241,15 +233,13 @@ export class JobListUi extends Component {
}
} else if (!isLoading && !hasJobs) {
content = this.renderEmpty();
} else if (isLoading) {
content = this.renderLoading();
} else {
content = this.renderList();
}
return (
<EuiPageContent horizontalPosition="center" className="rollupJobsListPanel">
{content}
</EuiPageContent>
);
return content;
}
}

View file

@ -22,6 +22,15 @@ jest.mock('../../services', () => {
};
});
jest.mock('../../services/documentation_links', () => {
const coreMocks = jest.requireActual('../../../../../../../src/core/public/mocks');
return {
init: jest.fn(),
documentationLinks: coreMocks.docLinksServiceMock.createStartContract().links,
};
});
const defaultProps = {
history: { location: {} },
loadJobs: () => {},
@ -52,14 +61,14 @@ describe('<JobList />', () => {
it('should display a loading message when loading the jobs', () => {
const { component, exists } = initTestBed({ isLoading: true });
expect(exists('jobListLoading')).toBeTruthy();
expect(exists('sectionLoading')).toBeTruthy();
expect(component.find('JobTable').length).toBeFalsy();
});
it('should display the <JobTable /> when there are jobs', () => {
const { component, exists } = initTestBed({ hasJobs: true });
expect(exists('jobListLoading')).toBeFalsy();
expect(exists('sectionLoading')).toBeFalsy();
expect(component.find('JobTable').length).toBeTruthy();
});
@ -71,21 +80,20 @@ describe('<JobList />', () => {
},
});
it('should display a callout with the status and the message', () => {
it('should display an error with the status and the message', () => {
expect(exists('jobListError')).toBeTruthy();
expect(find('jobListError').find('EuiText').text()).toEqual('400 Houston we got a problem.');
});
});
describe('when the user does not have the permission to access it', () => {
const { exists } = initTestBed({ jobLoadError: { status: 403 } });
const { exists, find } = initTestBed({ jobLoadError: { status: 403 } });
it('should render a callout message', () => {
it('should render an error message', () => {
expect(exists('jobListNoPermission')).toBeTruthy();
});
it('should display the page header', () => {
expect(exists('jobListPageHeader')).toBeTruthy();
expect(find('jobListNoPermission').find('EuiText').text()).toEqual(
'You do not have permission to view or add rollup jobs.'
);
});
});
});

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React, { Component, Fragment } from 'react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
@ -28,10 +28,11 @@ import {
EuiTableRowCellCheckbox,
EuiText,
EuiToolTip,
EuiButton,
} from '@elastic/eui';
import { UIM_SHOW_DETAILS_CLICK } from '../../../../../common';
import { METRIC_TYPE } from '../../../services';
import { METRIC_TYPE, getRouterLinkProps } from '../../../services';
import { trackUiMetric } from '../../../../kibana_services';
import { JobActionMenu, JobStatus } from '../../components';
@ -346,9 +347,9 @@ export class JobTable extends Component {
const atLeastOneItemSelected = Object.keys(idToSelectedJobMap).length > 0;
return (
<Fragment>
<EuiFlexGroup gutterSize="l" alignItems="center">
{atLeastOneItemSelected ? (
<div>
<EuiFlexGroup>
{atLeastOneItemSelected && (
<EuiFlexItem grow={false}>
<JobActionMenu
jobs={this.getSelectedJobs()}
@ -357,7 +358,7 @@ export class JobTable extends Component {
deselectJobs={this.deselectItems}
/>
</EuiFlexItem>
) : null}
)}
<EuiFlexItem>
<EuiFieldSearch
fullWidth
@ -372,6 +373,14 @@ export class JobTable extends Component {
aria-label="Search jobs"
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton fill {...getRouterLinkProps('/create')}>
<FormattedMessage
id="xpack.rollupJobs.jobList.createButtonLabel"
defaultMessage="Create rollup job"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="m" />
@ -409,7 +418,7 @@ export class JobTable extends Component {
<EuiSpacer size="m" />
{jobs.length > 0 ? this.renderPager() : null}
</Fragment>
</div>
);
}
}

View file

@ -20,6 +20,14 @@ jest.mock('../../../../kibana_services', () => {
};
});
jest.mock('../../../services', () => {
const services = jest.requireActual('../../../services');
return {
...services,
getRouterLinkProps: (link) => ({ href: link }),
};
});
const defaultProps = {
jobs: [],
pager: new Pager(20, 10, 1),

View file

@ -5,9 +5,7 @@
* 2.0.
*/
import { i18n } from '@kbn/i18n';
import { loadJobs as sendLoadJobsRequest, deserializeJobs, showApiError } from '../../services';
import { loadJobs as sendLoadJobsRequest, deserializeJobs } from '../../services';
import { LOAD_JOBS_START, LOAD_JOBS_SUCCESS, LOAD_JOBS_FAILURE } from '../action_types';
export const loadJobs = () => async (dispatch) => {
@ -19,17 +17,10 @@ export const loadJobs = () => async (dispatch) => {
try {
jobs = await sendLoadJobsRequest();
} catch (error) {
dispatch({
return dispatch({
type: LOAD_JOBS_FAILURE,
payload: { error },
});
return showApiError(
error,
i18n.translate('xpack.rollupJobs.loadAction.errorTitle', {
defaultMessage: 'Error loading rollup jobs',
})
);
}
dispatch({

View file

@ -5,4 +5,8 @@
* 2.0.
*/
export { extractQueryParams, indices } from '../../../../src/plugins/es_ui_shared/public';
export {
extractQueryParams,
indices,
SectionLoading,
} from '../../../../src/plugins/es_ui_shared/public';

View file

@ -5,10 +5,10 @@
* 2.0.
*/
import { getRouter, setHttp } from '../../crud_app/services';
import { getRouter, setHttp, init as initDocumentation } from '../../crud_app/services';
import { mockHttpRequest, pageHelpers, nextTick } from './helpers';
import { JOBS } from './helpers/constants';
import { coreMock } from '../../../../../../src/core/public/mocks';
import { coreMock, docLinksServiceMock } from '../../../../../../src/core/public/mocks';
jest.mock('../../crud_app/services', () => {
const services = jest.requireActual('../../crud_app/services');
@ -38,6 +38,7 @@ describe('<JobList />', () => {
beforeAll(() => {
startMock = coreMock.createStart();
setHttp(startMock.http);
initDocumentation(docLinksServiceMock.createStartContract());
});
beforeEach(async () => {

View file

@ -24,6 +24,15 @@ jest.mock('../../kibana_services', () => {
};
});
jest.mock('../../crud_app/services/documentation_links', () => {
const coreMocks = jest.requireActual('../../../../../../src/core/public/mocks');
return {
init: jest.fn(),
documentationLinks: coreMocks.docLinksServiceMock.createStartContract().links,
};
});
const { setup } = pageHelpers.jobList;
describe('Smoke test cloning an existing rollup job from job list', () => {

View file

@ -18015,7 +18015,6 @@
"xpack.rollupJobs.jobTable.selectRow": "この行 {id} を選択",
"xpack.rollupJobs.licenseCheckErrorMessage": "ライセンス確認失敗",
"xpack.rollupJobs.listBreadcrumbTitle": "ロールアップジョブ",
"xpack.rollupJobs.loadAction.errorTitle": "ロールアップジョブを読み込み中にエラーが発生",
"xpack.rollupJobs.refreshAction.errorTitle": "ロールアップジョブの更新中にエラーが発生",
"xpack.rollupJobs.rollupIndexPatternsDescription": "ロールアップインデックスを捕捉するインデックスパターンの作成を有効にします。\n それによりロールアップデータに基づくビジュアライゼーションが可能になります。",
"xpack.rollupJobs.rollupIndexPatternsTitle": "ロールアップインデックスパターンを有効にする",

View file

@ -18259,7 +18259,6 @@
"xpack.rollupJobs.jobTable.selectRow": "选择行 {id}",
"xpack.rollupJobs.licenseCheckErrorMessage": "许可证检查失败",
"xpack.rollupJobs.listBreadcrumbTitle": "汇总/打包作业",
"xpack.rollupJobs.loadAction.errorTitle": "加载汇总/打包作业时出错",
"xpack.rollupJobs.refreshAction.errorTitle": "刷新汇总/打包作业时出错",
"xpack.rollupJobs.rollupIndexPatternsDescription": "启用用于捕获汇总/打包索引的索引模式的创建,\n 汇总/打包索引反过来基于汇总/打包数据启用可视化。",
"xpack.rollupJobs.rollupIndexPatternsTitle": "启用汇总索引模式",