Skip to content

Commit 6dbdf06

Browse files
[Ingest Node Pipelines] Show flyout after editing or creating a pipeline (#64409)
* Show flyout after editing or creating a pipeline * JSX comment * Show not found flyout Copied from CCR * update not found flyout and fix behavior when viewing details from table * Reset pipeline name in URI when closing flyout * Remove encodeURI Already using encodingURIComponent for unsafe string. Co-authored-by: Alison Goryachev <alisonmllr20@gmail.com>
1 parent fc0ed64 commit 6dbdf06

7 files changed

Lines changed: 118 additions & 27 deletions

File tree

x-pack/plugins/ingest_pipelines/public/application/app.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ export const AppWithoutRouter = () => (
2626
<Route exact path={`${BASE_PATH}/create/:sourceName`} component={PipelinesClone} />
2727
<Route exact path={`${BASE_PATH}/create`} component={PipelinesCreate} />
2828
<Route exact path={`${BASE_PATH}/edit/:name`} component={PipelinesEdit} />
29+
{/* Catch all */}
30+
<Route component={PipelinesList} />
2931
</Switch>
3032
);
3133

x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_create/pipelines_create.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export const PipelinesCreate: React.FunctionComponent<RouteComponentProps & Prop
4949
return;
5050
}
5151

52-
history.push(BASE_PATH);
52+
history.push(BASE_PATH + `?pipeline=${pipeline.name}`);
5353
};
5454

5555
const onCancel = () => {

x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export const PipelinesEdit: React.FunctionComponent<RouteComponentProps<MatchPar
5454
return;
5555
}
5656

57-
history.push(BASE_PATH);
57+
history.push(BASE_PATH + `?pipeline=${updatedPipeline.name}`);
5858
};
5959

6060
const onCancel = () => {

x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details.tsx renamed to x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export interface Props {
3636
onClose: () => void;
3737
}
3838

39-
export const PipelineDetails: FunctionComponent<Props> = ({
39+
export const PipelineDetailsFlyout: FunctionComponent<Props> = ({
4040
pipeline,
4141
onClose,
4242
onEditClick,

x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/main.tsx

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import React, { useEffect, useState } from 'react';
88
import { RouteComponentProps } from 'react-router-dom';
99
import { i18n } from '@kbn/i18n';
1010
import { FormattedMessage } from '@kbn/i18n/react';
11+
import { Location } from 'history';
12+
import { parse } from 'query-string';
1113

1214
import {
1315
EuiPageBody,
@@ -28,33 +30,58 @@ import { UIM_PIPELINES_LIST_LOAD } from '../../constants';
2830

2931
import { EmptyList } from './empty_list';
3032
import { PipelineTable } from './table';
31-
import { PipelineDetails } from './details';
33+
import { PipelineDetailsFlyout } from './details_flyout';
34+
import { PipelineNotFoundFlyout } from './not_found_flyout';
3235
import { PipelineDeleteModal } from './delete_modal';
3336

34-
export const PipelinesList: React.FunctionComponent<RouteComponentProps> = ({ history }) => {
37+
const getPipelineNameFromLocation = (location: Location) => {
38+
const { pipeline } = parse(location.search.substring(1));
39+
return pipeline;
40+
};
41+
42+
export const PipelinesList: React.FunctionComponent<RouteComponentProps> = ({
43+
history,
44+
location,
45+
}) => {
3546
const { services } = useKibana();
47+
const pipelineNameFromLocation = getPipelineNameFromLocation(location);
3648

3749
const [selectedPipeline, setSelectedPipeline] = useState<Pipeline | undefined>(undefined);
50+
const [showFlyout, setShowFlyout] = useState<boolean>(false);
51+
3852
const [pipelinesToDelete, setPipelinesToDelete] = useState<string[]>([]);
3953

54+
const { data, isLoading, error, sendRequest } = services.api.useLoadPipelines();
55+
4056
// Track component loaded
4157
useEffect(() => {
4258
services.metric.trackUiMetric(UIM_PIPELINES_LIST_LOAD);
4359
services.breadcrumbs.setBreadcrumbs('home');
4460
}, [services.metric, services.breadcrumbs]);
4561

46-
const { data, isLoading, error, sendRequest } = services.api.useLoadPipelines();
62+
useEffect(() => {
63+
if (pipelineNameFromLocation && data?.length) {
64+
const pipeline = data.find(p => p.name === pipelineNameFromLocation);
65+
setSelectedPipeline(pipeline);
66+
setShowFlyout(true);
67+
}
68+
}, [pipelineNameFromLocation, data]);
4769

48-
let content: React.ReactNode;
70+
const goToEditPipeline = (name: string) => {
71+
history.push(`${BASE_PATH}/edit/${encodeURIComponent(name)}`);
72+
};
4973

50-
const editPipeline = (name: string) => {
51-
history.push(encodeURI(`${BASE_PATH}/edit/${encodeURIComponent(name)}`));
74+
const goToClonePipeline = (name: string) => {
75+
history.push(`${BASE_PATH}/create/${encodeURIComponent(name)}`);
5276
};
5377

54-
const clonePipeline = (name: string) => {
55-
history.push(encodeURI(`${BASE_PATH}/create/${encodeURIComponent(name)}`));
78+
const goHome = () => {
79+
setShowFlyout(false);
80+
history.push(BASE_PATH);
5681
};
5782

83+
let content: React.ReactNode;
84+
5885
if (isLoading) {
5986
content = (
6087
<SectionLoading>
@@ -68,17 +95,47 @@ export const PipelinesList: React.FunctionComponent<RouteComponentProps> = ({ hi
6895
content = (
6996
<PipelineTable
7097
onReloadClick={sendRequest}
71-
onEditPipelineClick={editPipeline}
98+
onEditPipelineClick={goToEditPipeline}
7299
onDeletePipelineClick={setPipelinesToDelete}
73-
onClonePipelineClick={clonePipeline}
74-
onViewPipelineClick={setSelectedPipeline}
100+
onClonePipelineClick={goToClonePipeline}
75101
pipelines={data}
76102
/>
77103
);
78104
} else {
79105
content = <EmptyList />;
80106
}
81107

108+
const renderFlyout = (): React.ReactNode => {
109+
if (!showFlyout) {
110+
return;
111+
}
112+
if (selectedPipeline) {
113+
return (
114+
<PipelineDetailsFlyout
115+
pipeline={selectedPipeline}
116+
onClose={() => {
117+
setSelectedPipeline(undefined);
118+
goHome();
119+
}}
120+
onEditClick={goToEditPipeline}
121+
onCloneClick={goToClonePipeline}
122+
onDeleteClick={setPipelinesToDelete}
123+
/>
124+
);
125+
} else {
126+
// Somehow we triggered show pipeline details, but do not have a pipeline.
127+
// We assume not found.
128+
return (
129+
<PipelineNotFoundFlyout
130+
onClose={() => {
131+
goHome();
132+
}}
133+
pipelineName={pipelineNameFromLocation}
134+
/>
135+
);
136+
}
137+
};
138+
82139
return (
83140
<>
84141
<EuiPageBody>
@@ -131,15 +188,7 @@ export const PipelinesList: React.FunctionComponent<RouteComponentProps> = ({ hi
131188
)}
132189
</EuiPageContent>
133190
</EuiPageBody>
134-
{selectedPipeline && (
135-
<PipelineDetails
136-
pipeline={selectedPipeline}
137-
onClose={() => setSelectedPipeline(undefined)}
138-
onEditClick={editPipeline}
139-
onCloneClick={clonePipeline}
140-
onDeleteClick={setPipelinesToDelete}
141-
/>
142-
)}
191+
{renderFlyout()}
143192
{pipelinesToDelete?.length > 0 ? (
144193
<PipelineDeleteModal
145194
callback={deleteResponse => {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import React, { FunctionComponent } from 'react';
8+
import { FormattedMessage } from '@kbn/i18n/react';
9+
import { EuiFlyout, EuiFlyoutBody, EuiCallOut } from '@elastic/eui';
10+
import { EuiFlyoutHeader, EuiTitle } from '@elastic/eui';
11+
12+
interface Props {
13+
onClose: () => void;
14+
pipelineName: string | string[] | null | undefined;
15+
}
16+
17+
export const PipelineNotFoundFlyout: FunctionComponent<Props> = ({ onClose, pipelineName }) => {
18+
return (
19+
<EuiFlyout onClose={onClose} size="m" maxWidth={550}>
20+
<EuiFlyoutHeader>
21+
{pipelineName && (
22+
<EuiTitle id="notFoundFlyoutTitle">
23+
<h2>{pipelineName}</h2>
24+
</EuiTitle>
25+
)}
26+
</EuiFlyoutHeader>
27+
28+
<EuiFlyoutBody>
29+
<EuiCallOut
30+
title={
31+
<FormattedMessage
32+
id="xpack.ingestPipelines.list.notFoundFlyoutMessage"
33+
defaultMessage="Pipeline not found"
34+
/>
35+
}
36+
color="danger"
37+
iconType="alert"
38+
/>
39+
</EuiFlyoutBody>
40+
</EuiFlyout>
41+
);
42+
};

x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export interface Props {
1717
onEditPipelineClick: (pipelineName: string) => void;
1818
onClonePipelineClick: (pipelineName: string) => void;
1919
onDeletePipelineClick: (pipelineName: string[]) => void;
20-
onViewPipelineClick: (pipeline: Pipeline) => void;
2120
}
2221

2322
export const PipelineTable: FunctionComponent<Props> = ({
@@ -26,7 +25,6 @@ export const PipelineTable: FunctionComponent<Props> = ({
2625
onEditPipelineClick,
2726
onClonePipelineClick,
2827
onDeletePipelineClick,
29-
onViewPipelineClick,
3028
}) => {
3129
const [selection, setSelection] = useState<Pipeline[]>([]);
3230

@@ -94,8 +92,8 @@ export const PipelineTable: FunctionComponent<Props> = ({
9492
defaultMessage: 'Name',
9593
}),
9694
sortable: true,
97-
render: (name: string, pipeline) => (
98-
<EuiLink onClick={() => onViewPipelineClick(pipeline)}>{name}</EuiLink>
95+
render: (name: string) => (
96+
<EuiLink href={`#${BASE_PATH}?pipeline=${name}`}>{name}</EuiLink>
9997
),
10098
},
10199
{

0 commit comments

Comments
 (0)