diff --git a/x-pack/plugins/streams_app/public/components/entity_detail_view/index.tsx b/x-pack/plugins/streams_app/public/components/entity_detail_view/index.tsx index d2ce4859e66d1..68c5f9d6798ec 100644 --- a/x-pack/plugins/streams_app/public/components/entity_detail_view/index.tsx +++ b/x-pack/plugins/streams_app/public/components/entity_detail_view/index.tsx @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { EuiFlexGroup, EuiIcon, EuiLink, EuiPanel } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiLink, EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { useStreamsAppBreadcrumbs } from '../../hooks/use_streams_app_breadcrumbs'; @@ -71,31 +71,35 @@ export function EntityDetailViewWithoutParams({ return ( - - - - - {i18n.translate('xpack.streams.entityDetailView.goBackLinkLabel', { - defaultMessage: 'Back', + + + + + + {i18n.translate('xpack.streams.entityDetailView.goBackLinkLabel', { + defaultMessage: 'Back', + })} + + + + + + } + > + { + return { + name: tabKey, + label, + href, + selected: selectedTab === tabKey, + }; })} - - - - } - > - { - return { - name: tabKey, - label, - href, - selected: selectedTab === tabKey, - }; - })} - /> - + /> + + {selectedTabObject.content} ); diff --git a/x-pack/plugins/streams_app/public/components/stream_detail_enriching/index.tsx b/x-pack/plugins/streams_app/public/components/stream_detail_enriching/index.tsx new file mode 100644 index 0000000000000..d879142162353 --- /dev/null +++ b/x-pack/plugins/streams_app/public/components/stream_detail_enriching/index.tsx @@ -0,0 +1,18 @@ +/* + * 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 { StreamDefinition } from '@kbn/streams-plugin/common'; +import React from 'react'; + +export function StreamDetailEnriching({ + definition: _definition, + refreshDefinition: _refreshDefinition, +}: { + definition?: StreamDefinition; + refreshDefinition: () => void; +}) { + return <>{'TODO'}; +} diff --git a/x-pack/plugins/streams_app/public/components/stream_detail_management/index.tsx b/x-pack/plugins/streams_app/public/components/stream_detail_management/index.tsx new file mode 100644 index 0000000000000..534d883905b17 --- /dev/null +++ b/x-pack/plugins/streams_app/public/components/stream_detail_management/index.tsx @@ -0,0 +1,92 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { StreamDefinition } from '@kbn/streams-plugin/common'; +import { EuiButtonGroup, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { useStreamsAppParams } from '../../hooks/use_streams_app_params'; +import { RedirectTo } from '../redirect_to'; +import { useStreamsAppRouter } from '../../hooks/use_streams_app_router'; +import { StreamDetailRouting } from '../stream_detail_routing'; +import { StreamDetailEnriching } from '../stream_detail_enriching'; +import { StreamDetailSchemaEditor } from '../stream_detail_schema_editor'; + +type ManagementSubTabs = 'route' | 'enrich' | 'schemaEditor'; + +function isValidManagementSubTab(value: string): value is ManagementSubTabs { + return ['route', 'enrich', 'schemaEditor'].includes(value); +} + +export function StreamDetailManagement({ + definition, + refreshDefinition, +}: { + definition?: StreamDefinition; + refreshDefinition: () => void; +}) { + const { + path: { key, subtab }, + } = useStreamsAppParams('/{key}/management/{subtab}'); + const router = useStreamsAppRouter(); + + const tabs = { + route: { + content: ( + + ), + label: i18n.translate('xpack.streams.streamDetailView.routingTab', { + defaultMessage: 'Streams Partitioning', + }), + }, + enrich: { + content: ( + + ), + label: i18n.translate('xpack.streams.streamDetailView.enrichingTab', { + defaultMessage: 'Extract field', + }), + }, + schemaEditor: { + content: ( + + ), + label: i18n.translate('xpack.streams.streamDetailView.schemaEditorTab', { + defaultMessage: 'Schema editor', + }), + }, + }; + + if (!isValidManagementSubTab(subtab)) { + return ( + + ); + } + + const selectedTabObject = tabs[subtab]; + + return ( + + + { + router.push('/{key}/management/{subtab}', { + path: { key, subtab: optionId }, + query: {}, + }); + }} + options={Object.keys(tabs).map((id) => ({ + id, + label: tabs[id as ManagementSubTabs].label, + }))} + /> + + {selectedTabObject.content} + + ); +} diff --git a/x-pack/plugins/streams_app/public/components/stream_detail_overview/index.tsx b/x-pack/plugins/streams_app/public/components/stream_detail_overview/index.tsx index 93a573fd4c01f..c051d114317ea 100644 --- a/x-pack/plugins/streams_app/public/components/stream_detail_overview/index.tsx +++ b/x-pack/plugins/streams_app/public/components/stream_detail_overview/index.tsx @@ -114,54 +114,58 @@ export function StreamDetailOverview({ definition }: { definition?: StreamDefini return ( <> - - - { - if (!isUpdate) { + + + + { + if (!isUpdate) { + histogramQueryFetch.refresh(); + return; + } + + if (dateRange) { + setTimeRange({ from: dateRange.from, to: dateRange?.to, mode: dateRange.mode }); + } + }} + onRefresh={() => { histogramQueryFetch.refresh(); - return; - } - - if (dateRange) { - setTimeRange({ from: dateRange.from, to: dateRange?.to, mode: dateRange.mode }); - } - }} - onRefresh={() => { - histogramQueryFetch.refresh(); - }} - placeholder={i18n.translate( - 'xpack.streams.entityDetailOverview.searchBarPlaceholder', - { - defaultMessage: 'Filter data by using KQL', - } - )} - dateRangeFrom={timeRange.from} - dateRangeTo={timeRange.to} - /> - - - {i18n.translate('xpack.streams.streamDetailOverview.openInDiscoverButtonLabel', { - defaultMessage: 'Open in Discover', - })} - - - - - + }} + placeholder={i18n.translate( + 'xpack.streams.entityDetailOverview.searchBarPlaceholder', + { + defaultMessage: 'Filter data by using KQL', + } + )} + dateRangeFrom={timeRange.from} + dateRangeTo={timeRange.to} + /> + + + {i18n.translate('xpack.streams.streamDetailOverview.openInDiscoverButtonLabel', { + defaultMessage: 'Open in Discover', + })} + - + + + + + + + + ); diff --git a/x-pack/plugins/streams_app/public/components/stream_detail_routing/index.tsx b/x-pack/plugins/streams_app/public/components/stream_detail_routing/index.tsx new file mode 100644 index 0000000000000..af65c7eab4235 --- /dev/null +++ b/x-pack/plugins/streams_app/public/components/stream_detail_routing/index.tsx @@ -0,0 +1,18 @@ +/* + * 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 { StreamDefinition } from '@kbn/streams-plugin/common'; +import React from 'react'; + +export function StreamDetailRouting({ + definition: _definition, + refreshDefinition: _refreshDefinition, +}: { + definition?: StreamDefinition; + refreshDefinition: () => void; +}) { + return <>{'TODO'}; +} diff --git a/x-pack/plugins/streams_app/public/components/stream_detail_schema_editor/index.tsx b/x-pack/plugins/streams_app/public/components/stream_detail_schema_editor/index.tsx new file mode 100644 index 0000000000000..7d3e9322e8d4f --- /dev/null +++ b/x-pack/plugins/streams_app/public/components/stream_detail_schema_editor/index.tsx @@ -0,0 +1,18 @@ +/* + * 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 { StreamDefinition } from '@kbn/streams-plugin/common'; +import React from 'react'; + +export function StreamDetailSchemaEditor({ + definition: _definition, + refreshDefinition: _refreshDefinition, +}: { + definition?: StreamDefinition; + refreshDefinition: () => void; +}) { + return <>{'TODO'}; +} diff --git a/x-pack/plugins/streams_app/public/components/stream_detail_view/index.tsx b/x-pack/plugins/streams_app/public/components/stream_detail_view/index.tsx index ebf72a58d32a8..4f213e855c175 100644 --- a/x-pack/plugins/streams_app/public/components/stream_detail_view/index.tsx +++ b/x-pack/plugins/streams_app/public/components/stream_detail_view/index.tsx @@ -11,11 +11,13 @@ import { useStreamsAppParams } from '../../hooks/use_streams_app_params'; import { useStreamsAppFetch } from '../../hooks/use_streams_app_fetch'; import { useKibana } from '../../hooks/use_kibana'; import { StreamDetailOverview } from '../stream_detail_overview'; +import { StreamDetailManagement } from '../stream_detail_management'; export function StreamDetailView() { - const { - path: { key, tab }, - } = useStreamsAppParams('/{key}/{tab}'); + const { path } = useStreamsAppParams('/{key}/*'); + + const key = path.key; + const tab = 'tab' in path ? path.tab : 'management'; const { dependencies: { @@ -25,7 +27,7 @@ export function StreamDetailView() { }, } = useKibana(); - const { value: streamEntity } = useStreamsAppFetch( + const { value: streamEntity, refresh } = useStreamsAppFetch( ({ signal }) => { return streamsRepositoryClient.fetch('GET /api/streams/{id}', { signal, @@ -54,7 +56,7 @@ export function StreamDetailView() { }, { name: 'management', - content: <>, + content: , label: i18n.translate('xpack.streams.streamDetailView.managementTab', { defaultMessage: 'Management', }), diff --git a/x-pack/plugins/streams_app/public/components/stream_list_view/index.tsx b/x-pack/plugins/streams_app/public/components/stream_list_view/index.tsx index e0530fc6bf5f0..7ffda5f40295a 100644 --- a/x-pack/plugins/streams_app/public/components/stream_list_view/index.tsx +++ b/x-pack/plugins/streams_app/public/components/stream_list_view/index.tsx @@ -6,7 +6,7 @@ */ import React, { useState } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiFlexGroup, EuiSearchBar } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiSearchBar } from '@elastic/eui'; import { useKibana } from '../../hooks/use_kibana'; import { useStreamsAppFetch } from '../../hooks/use_streams_app_fetch'; import { StreamsAppPageHeader } from '../streams_app_page_header'; @@ -36,27 +36,33 @@ export function StreamListView() { return ( - - } - /> + + + } + /> + - { - setQuery(nextQuery.queryText); - }} - /> - + + { + setQuery(nextQuery.queryText); + }} + /> + + + + diff --git a/x-pack/plugins/streams_app/public/components/streams_app_page_body/index.tsx b/x-pack/plugins/streams_app/public/components/streams_app_page_body/index.tsx index 0f13dc31e277b..04b44f82df0fd 100644 --- a/x-pack/plugins/streams_app/public/components/streams_app_page_body/index.tsx +++ b/x-pack/plugins/streams_app/public/components/streams_app_page_body/index.tsx @@ -17,6 +17,7 @@ export function StreamsAppPageBody({ children }: { children: React.ReactNode }) className={css` border-top: 1px solid ${theme.colors.lightShade}; border-radius: 0px; + display: flex; `} paddingSize="l" > diff --git a/x-pack/plugins/streams_app/public/components/streams_app_page_template/index.tsx b/x-pack/plugins/streams_app/public/components/streams_app_page_template/index.tsx index c474f54c22745..942d2937dba81 100644 --- a/x-pack/plugins/streams_app/public/components/streams_app_page_template/index.tsx +++ b/x-pack/plugins/streams_app/public/components/streams_app_page_template/index.tsx @@ -35,7 +35,15 @@ export function StreamsAppPageTemplate({ children }: { children: React.ReactNode }, }} > - + {children} diff --git a/x-pack/plugins/streams_app/public/hooks/use_streams_app_params.ts b/x-pack/plugins/streams_app/public/hooks/use_streams_app_params.ts index 2931a6fa64f8b..d7a6e175e5491 100644 --- a/x-pack/plugins/streams_app/public/hooks/use_streams_app_params.ts +++ b/x-pack/plugins/streams_app/public/hooks/use_streams_app_params.ts @@ -8,7 +8,8 @@ import { type PathsOf, type TypeOf, useParams } from '@kbn/typed-react-router-co import type { StreamsAppRoutes } from '../routes/config'; export function useStreamsAppParams>( - path: TPath + path: TPath, + optional: boolean = false ): TypeOf { - return useParams(path)! as TypeOf; + return useParams(path, optional)! as TypeOf; } diff --git a/x-pack/plugins/streams_app/public/routes/config.tsx b/x-pack/plugins/streams_app/public/routes/config.tsx index e3efdc6d871e7..6ae0fec51ad7a 100644 --- a/x-pack/plugins/streams_app/public/routes/config.tsx +++ b/x-pack/plugins/streams_app/public/routes/config.tsx @@ -44,6 +44,22 @@ const streamsAppRoutes = { '/{key}': { element: , }, + '/{key}/management': { + element: ( + + ), + }, + '/{key}/management/{subtab}': { + element: , + params: t.type({ + path: t.type({ + subtab: t.string, + }), + }), + }, '/{key}/{tab}': { element: , params: t.type({