diff --git a/x-pack/plugins/ingest_pipelines/public/application/app.tsx b/x-pack/plugins/ingest_pipelines/public/application/app.tsx index 2ec72267701d74..ba7675b5075960 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/app.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/app.tsx @@ -26,6 +26,8 @@ export const AppWithoutRouter = () => ( + {/* Catch all */} + ); diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_create/pipelines_create.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_create/pipelines_create.tsx index 2f3e2630adbd10..15d370975c9f8b 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_create/pipelines_create.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_create/pipelines_create.tsx @@ -50,7 +50,7 @@ export const PipelinesCreate: React.FunctionComponent { diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx index 02eba9c4f620f3..c70d512970b2cd 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx @@ -53,7 +53,7 @@ export const PipelinesEdit: React.FunctionComponent { diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx similarity index 98% rename from x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details.tsx rename to x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx index 07fdb1c15e0bf4..98243a5149c0df 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx @@ -36,7 +36,7 @@ export interface Props { onClose: () => void; } -export const PipelineDetails: FunctionComponent = ({ +export const PipelineDetailsFlyout: FunctionComponent = ({ pipeline, onClose, onEditClick, diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/main.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/main.tsx index bd0043e3e74af2..2be9776ae06112 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/main.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/main.tsx @@ -8,6 +8,8 @@ import React, { useEffect, useState } from 'react'; import { RouteComponentProps } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { Location } from 'history'; +import { parse } from 'query-string'; import { EuiPageBody, @@ -28,33 +30,58 @@ import { UIM_PIPELINES_LIST_LOAD } from '../../constants'; import { EmptyList } from './empty_list'; import { PipelineTable } from './table'; -import { PipelineDetails } from './details'; +import { PipelineDetailsFlyout } from './details_flyout'; +import { PipelineNotFoundFlyout } from './not_found_flyout'; import { PipelineDeleteModal } from './delete_modal'; -export const PipelinesList: React.FunctionComponent = ({ history }) => { +const getPipelineNameFromLocation = (location: Location) => { + const { pipeline } = parse(location.search.substring(1)); + return pipeline; +}; + +export const PipelinesList: React.FunctionComponent = ({ + history, + location, +}) => { const { services } = useKibana(); + const pipelineNameFromLocation = getPipelineNameFromLocation(location); const [selectedPipeline, setSelectedPipeline] = useState(undefined); + const [showFlyout, setShowFlyout] = useState(false); + const [pipelinesToDelete, setPipelinesToDelete] = useState([]); + const { data, isLoading, error, sendRequest } = services.api.useLoadPipelines(); + // Track component loaded useEffect(() => { services.metric.trackUiMetric(UIM_PIPELINES_LIST_LOAD); services.breadcrumbs.setBreadcrumbs('home'); }, [services.metric, services.breadcrumbs]); - const { data, isLoading, error, sendRequest } = services.api.useLoadPipelines(); + useEffect(() => { + if (pipelineNameFromLocation && data?.length) { + const pipeline = data.find(p => p.name === pipelineNameFromLocation); + setSelectedPipeline(pipeline); + setShowFlyout(true); + } + }, [pipelineNameFromLocation, data]); - let content: React.ReactNode; + const goToEditPipeline = (name: string) => { + history.push(`${BASE_PATH}/edit/${encodeURIComponent(name)}`); + }; - const editPipeline = (name: string) => { - history.push(encodeURI(`${BASE_PATH}/edit/${encodeURIComponent(name)}`)); + const goToClonePipeline = (name: string) => { + history.push(`${BASE_PATH}/create/${encodeURIComponent(name)}`); }; - const clonePipeline = (name: string) => { - history.push(encodeURI(`${BASE_PATH}/create/${encodeURIComponent(name)}`)); + const goHome = () => { + setShowFlyout(false); + history.push(BASE_PATH); }; + let content: React.ReactNode; + if (isLoading) { content = ( @@ -68,10 +95,9 @@ export const PipelinesList: React.FunctionComponent = ({ hi content = ( ); @@ -79,6 +105,37 @@ export const PipelinesList: React.FunctionComponent = ({ hi content = ; } + const renderFlyout = (): React.ReactNode => { + if (!showFlyout) { + return; + } + if (selectedPipeline) { + return ( + { + setSelectedPipeline(undefined); + goHome(); + }} + onEditClick={goToEditPipeline} + onCloneClick={goToClonePipeline} + onDeleteClick={setPipelinesToDelete} + /> + ); + } else { + // Somehow we triggered show pipeline details, but do not have a pipeline. + // We assume not found. + return ( + { + goHome(); + }} + pipelineName={pipelineNameFromLocation} + /> + ); + } + }; + return ( <> @@ -131,15 +188,7 @@ export const PipelinesList: React.FunctionComponent = ({ hi )} - {selectedPipeline && ( - setSelectedPipeline(undefined)} - onEditClick={editPipeline} - onCloneClick={clonePipeline} - onDeleteClick={setPipelinesToDelete} - /> - )} + {renderFlyout()} {pipelinesToDelete?.length > 0 ? ( { diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/not_found_flyout.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/not_found_flyout.tsx new file mode 100644 index 00000000000000..b967e54187ced1 --- /dev/null +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/not_found_flyout.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FunctionComponent } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiFlyout, EuiFlyoutBody, EuiCallOut } from '@elastic/eui'; +import { EuiFlyoutHeader, EuiTitle } from '@elastic/eui'; + +interface Props { + onClose: () => void; + pipelineName: string | string[] | null | undefined; +} + +export const PipelineNotFoundFlyout: FunctionComponent = ({ onClose, pipelineName }) => { + return ( + + + {pipelineName && ( + +

{pipelineName}

+
+ )} +
+ + + + } + color="danger" + iconType="alert" + /> + +
+ ); +}; diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx index 05488f46c148e7..1c938a023fc2cc 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/table.tsx @@ -17,7 +17,6 @@ export interface Props { onEditPipelineClick: (pipelineName: string) => void; onClonePipelineClick: (pipelineName: string) => void; onDeletePipelineClick: (pipelineName: string[]) => void; - onViewPipelineClick: (pipeline: Pipeline) => void; } export const PipelineTable: FunctionComponent = ({ @@ -26,7 +25,6 @@ export const PipelineTable: FunctionComponent = ({ onEditPipelineClick, onClonePipelineClick, onDeletePipelineClick, - onViewPipelineClick, }) => { const [selection, setSelection] = useState([]); @@ -94,8 +92,8 @@ export const PipelineTable: FunctionComponent = ({ defaultMessage: 'Name', }), sortable: true, - render: (name: string, pipeline) => ( - onViewPipelineClick(pipeline)}>{name} + render: (name: string) => ( + {name} ), }, {