🌊 Streams: Convert legacy types in frontend (#208608)

This PR gets rid of the usage of the legacy "readdefinition" types in
the frontend except for the enrichment view, because @tonyghiani is
working on that in parallel.

I first looked into whether we can just use the existing
`IngestStreamGetResponse` type, but since it doesn't carry the name of
the stream, that is actually super annoying to use - passing the name as
a separate argument is pretty annoying and increases the risk of bugs.

Even though it's not fully "Elasticsearch"-y, I decided to add the
stream name to the `IngestStreamGetResponse` - this way the `stream`
property in the response is a regular `StreamDefinition`, so all the
functions that act on it can use it right away.

This simplifies the frontend code without hurting programmatic API
users.
This commit is contained in:
Joe Reuter 2025-01-30 19:36:59 +01:00 committed by GitHub
parent aec58c14ef
commit 2212a19bc8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 170 additions and 159 deletions

View file

@ -19,8 +19,10 @@ import {
WiredIngest,
WiredStreamDefinition,
unwiredIngestSchema,
unwiredStreamDefinitionSchema,
unwiredStreamDefinitionSchemaBase,
wiredIngestSchema,
wiredStreamDefinitionSchema,
wiredStreamDefinitionSchemaBase,
} from './base';
import { ElasticsearchAsset, elasticsearchAssetSchema } from './common';
@ -73,13 +75,13 @@ const ingestUpsertRequestSchema: z.Schema<IngestUpsertRequest> = z.union([
* Stream get response
*/
interface WiredStreamGetResponse extends StreamGetResponseBase {
stream: Omit<WiredStreamDefinition, 'name'>;
stream: WiredStreamDefinition;
inherited_fields: InheritedFieldDefinition;
effective_lifecycle: WiredIngestStreamEffectiveLifecycle;
}
interface UnwiredStreamGetResponse extends StreamGetResponseBase {
stream: Omit<UnwiredStreamDefinition, 'name'>;
stream: UnwiredStreamDefinition;
elasticsearch_assets: ElasticsearchAsset[];
data_stream_exists: boolean;
effective_lifecycle: UnwiredIngestStreamEffectiveLifecycle;
@ -123,7 +125,7 @@ const ingestStreamUpsertRequestSchema: z.Schema<IngestStreamUpsertRequest> = z.u
const wiredStreamGetResponseSchema: z.Schema<WiredStreamGetResponse> = z.intersection(
streamGetResponseSchemaBase,
z.object({
stream: wiredStreamDefinitionSchemaBase,
stream: wiredStreamDefinitionSchema,
inherited_fields: inheritedFieldDefinitionSchema,
effective_lifecycle: wiredIngestStreamEffectiveLifecycleSchema,
})
@ -132,7 +134,7 @@ const wiredStreamGetResponseSchema: z.Schema<WiredStreamGetResponse> = z.interse
const unwiredStreamGetResponseSchema: z.Schema<UnwiredStreamGetResponse> = z.intersection(
streamGetResponseSchemaBase,
z.object({
stream: unwiredStreamDefinitionSchemaBase,
stream: unwiredStreamDefinitionSchema,
elasticsearch_assets: z.array(elasticsearchAssetSchema),
data_stream_exists: z.boolean(),
effective_lifecycle: unwiredIngestStreamEffectiveLifecycleSchema,

View file

@ -5,7 +5,6 @@
* 2.0.
*/
import { omit } from 'lodash';
import {
IngestStreamGetResponse,
InheritedFieldDefinition,
@ -50,7 +49,7 @@ export async function readStream({
if (isUnwiredStreamDefinition(streamDefinition)) {
return {
stream: omit(streamDefinition, 'name'),
stream: streamDefinition,
elasticsearch_assets: dataStream
? await getUnmanagedElasticsearchAssets({
dataStream,
@ -65,7 +64,7 @@ export async function readStream({
}
const body: WiredStreamGetResponse = {
stream: omit(streamDefinition, 'name'),
stream: streamDefinition,
dashboards,
effective_lifecycle: findInheritedLifecycle(streamDefinition, ancestors),
inherited_fields: ancestors.reduce((acc, def) => {

View file

@ -11,7 +11,7 @@ import { css } from '@emotion/css';
import { ILM_LOCATOR_ID, IlmLocatorParams } from '@kbn/index-lifecycle-management-common-shared';
import {
IngestStreamEffectiveLifecycle,
ReadStreamDefinition,
IngestStreamGetResponse,
isDslLifecycle,
isErrorLifecycle,
isIlmLifecycle,
@ -44,7 +44,7 @@ export function EntityDetailViewWithoutParams({
displayName?: string;
id: string;
};
definition?: ReadStreamDefinition;
definition?: IngestStreamGetResponse;
}) {
const router = useStreamsAppRouter();
useStreamsAppBreadcrumbs(() => {

View file

@ -6,21 +6,25 @@
*/
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSearchBar } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { ReadStreamDefinition } from '@kbn/streams-schema';
import React, { useMemo, useState } from 'react';
import type { SanitizedDashboardAsset } from '@kbn/streams-plugin/server/routes/dashboards/route';
import { IngestStreamGetResponse } from '@kbn/streams-schema';
import { AddDashboardFlyout } from './add_dashboard_flyout';
import { DashboardsTable } from './dashboard_table';
import { useDashboardsApi } from '../../hooks/use_dashboards_api';
import { useDashboardsFetch } from '../../hooks/use_dashboards_fetch';
export function StreamDetailDashboardsView({ definition }: { definition?: ReadStreamDefinition }) {
export function StreamDetailDashboardsView({
definition,
}: {
definition?: IngestStreamGetResponse;
}) {
const [query, setQuery] = useState('');
const [isAddDashboardFlyoutOpen, setIsAddDashboardFlyoutOpen] = useState(false);
const dashboardsFetch = useDashboardsFetch(definition?.name);
const { addDashboards, removeDashboards } = useDashboardsApi(definition?.name);
const dashboardsFetch = useDashboardsFetch(definition?.stream.name);
const { addDashboards, removeDashboards } = useDashboardsApi(definition?.stream.name);
const [isUnlinkLoading, setIsUnlinkLoading] = useState(false);
const linkedDashboards = useMemo(() => {
@ -95,7 +99,7 @@ export function StreamDetailDashboardsView({ definition }: { definition?: ReadSt
{definition && isAddDashboardFlyoutOpen ? (
<AddDashboardFlyout
linkedDashboards={linkedDashboards}
entityId={definition.name}
entityId={definition.stream.name}
onAddDashboards={async (dashboards) => {
await addDashboards(dashboards);
await dashboardsFetch.refresh();

View file

@ -4,9 +4,9 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import React, { useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { UnwiredReadStreamDefinition } from '@kbn/streams-schema';
import { UnwiredStreamGetResponse } from '@kbn/streams-schema';
import { EuiCallOut, EuiFlexGroup, EuiListGroup, EuiText } from '@elastic/eui';
import { useStreamsAppParams } from '../../hooks/use_streams_app_params';
import { RedirectTo } from '../redirect_to';
@ -24,13 +24,30 @@ export function ClassicStreamDetailManagement({
definition,
refreshDefinition,
}: {
definition: UnwiredReadStreamDefinition;
definition: UnwiredStreamGetResponse;
refreshDefinition: () => void;
}) {
const {
path: { key, subtab },
} = useStreamsAppParams('/{key}/management/{subtab}');
const legacyDefinition = useMemo(() => {
if (!definition) {
return undefined;
}
return {
dashboards: definition.dashboards,
elasticsearch_assets: definition.elasticsearch_assets,
inherited_fields: {},
effective_lifecycle: definition.effective_lifecycle,
name: definition.stream.name,
data_stream_exists: definition.data_stream_exists,
stream: {
...definition.stream,
},
};
}, [definition]);
const tabs: ManagementTabs = {
overview: {
content: <UnmanagedStreamOverview definition={definition} />,
@ -43,7 +60,10 @@ export function ClassicStreamDetailManagement({
if (definition.data_stream_exists) {
tabs.enrich = {
content: (
<StreamDetailEnrichment definition={definition} refreshDefinition={refreshDefinition} />
<StreamDetailEnrichment
definition={legacyDefinition}
refreshDefinition={refreshDefinition}
/>
),
label: i18n.translate('xpack.streams.streamDetailView.enrichmentTab', {
defaultMessage: 'Extract field',
@ -63,7 +83,7 @@ export function ClassicStreamDetailManagement({
return <Wrapper tabs={tabs} streamId={key} subtab={subtab} />;
}
function UnmanagedStreamOverview({ definition }: { definition: UnwiredReadStreamDefinition }) {
function UnmanagedStreamOverview({ definition }: { definition: UnwiredStreamGetResponse }) {
const {
core: {
http: { basePath },

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React from 'react';
import { isWiredReadStream, ReadStreamDefinition } from '@kbn/streams-schema';
import { IngestStreamGetResponse, isWiredStreamGetResponse } from '@kbn/streams-schema';
import { WiredStreamDetailManagement } from './wired';
import { ClassicStreamDetailManagement } from './classic';
@ -14,7 +14,7 @@ export function StreamDetailManagement({
refreshDefinition,
isLoadingDefinition,
}: {
definition?: ReadStreamDefinition;
definition?: IngestStreamGetResponse;
refreshDefinition: () => void;
isLoadingDefinition: boolean;
}) {
@ -22,7 +22,7 @@ export function StreamDetailManagement({
return null;
}
if (isWiredReadStream(definition)) {
if (isWiredStreamGetResponse(definition)) {
return (
<WiredStreamDetailManagement
definition={definition}

View file

@ -4,9 +4,9 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import React, { useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { WiredReadStreamDefinition } from '@kbn/streams-schema';
import { WiredStreamGetResponse } from '@kbn/streams-schema';
import { useStreamsAppParams } from '../../hooks/use_streams_app_params';
import { RedirectTo } from '../redirect_to';
import { StreamDetailRouting } from '../stream_detail_routing';
@ -25,7 +25,7 @@ export function WiredStreamDetailManagement({
refreshDefinition,
isLoadingDefinition,
}: {
definition?: WiredReadStreamDefinition;
definition?: WiredStreamGetResponse;
refreshDefinition: () => void;
isLoadingDefinition: boolean;
}) {
@ -33,6 +33,22 @@ export function WiredStreamDetailManagement({
path: { key, subtab },
} = useStreamsAppParams('/{key}/management/{subtab}');
const legacyDefinition = useMemo(() => {
if (!definition) {
return undefined;
}
return {
dashboards: definition.dashboards,
inherited_fields: definition.inherited_fields,
elasticsearch_assets: [],
effective_lifecycle: definition.effective_lifecycle,
name: definition.stream.name,
stream: {
...definition.stream,
},
};
}, [definition]);
const tabs = {
route: {
content: (
@ -44,7 +60,10 @@ export function WiredStreamDetailManagement({
},
enrich: {
content: (
<StreamDetailEnrichment definition={definition} refreshDefinition={refreshDefinition} />
<StreamDetailEnrichment
definition={legacyDefinition}
refreshDefinition={refreshDefinition}
/>
),
label: i18n.translate('xpack.streams.streamDetailView.enrichmentTab', {
defaultMessage: 'Extract field',

View file

@ -20,9 +20,8 @@ import moment from 'moment';
import React, { useMemo } from 'react';
import { css } from '@emotion/css';
import {
ReadStreamDefinition,
isUnwiredReadStream,
isWiredReadStream,
IngestStreamGetResponse,
isUnWiredStreamGetResponse,
isWiredStreamDefinition,
} from '@kbn/streams-schema';
import { useDateRange } from '@kbn/observability-utils-browser/hooks/use_date_range';
@ -44,7 +43,7 @@ const formatNumber = (val: number) => {
});
};
export function StreamDetailOverview({ definition }: { definition?: ReadStreamDefinition }) {
export function StreamDetailOverview({ definition }: { definition?: IngestStreamGetResponse }) {
const {
dependencies: {
start: {
@ -131,14 +130,17 @@ export function StreamDetailOverview({ definition }: { definition?: ReadStreamDe
const docCountFetch = useStreamsAppFetch(
async ({ signal }) => {
if (!definition || (isUnwiredReadStream(definition) && !definition.data_stream_exists)) {
if (
!definition ||
(isUnWiredStreamGetResponse(definition) && !definition.data_stream_exists)
) {
return undefined;
}
return streamsRepositoryClient.fetch('GET /api/streams/{id}/_details', {
signal,
params: {
path: {
id: definition.name as string,
id: definition.stream.name,
},
query: {
start: String(start),
@ -154,14 +156,14 @@ export function StreamDetailOverview({ definition }: { definition?: ReadStreamDe
const [selectedTab, setSelectedTab] = React.useState<string | undefined>(undefined);
const tabs = [
...(definition && isWiredReadStream(definition)
...(definition && isWiredStreamDefinition(definition.stream)
? [
{
id: 'streams',
name: i18n.translate('xpack.streams.entityDetailOverview.tabs.streams', {
defaultMessage: 'Streams',
}),
content: <ChildStreamList stream={definition} />,
content: <ChildStreamList definition={definition} />,
},
]
: []),
@ -170,7 +172,7 @@ export function StreamDetailOverview({ definition }: { definition?: ReadStreamDe
name: i18n.translate('xpack.streams.entityDetailOverview.tabs.quicklinks', {
defaultMessage: 'Quick Links',
}),
content: <QuickLinks stream={definition} />,
content: <QuickLinks definition={definition} />,
},
];
@ -274,8 +276,8 @@ export function StreamDetailOverview({ definition }: { definition?: ReadStreamDe
const EMPTY_DASHBOARD_LIST: SanitizedDashboardAsset[] = [];
function QuickLinks({ stream }: { stream?: ReadStreamDefinition }) {
const dashboardsFetch = useDashboardsFetch(stream?.name);
function QuickLinks({ definition }: { definition?: IngestStreamGetResponse }) {
const dashboardsFetch = useDashboardsFetch(definition?.stream.name);
return (
<DashboardsTable
@ -285,7 +287,7 @@ function QuickLinks({ stream }: { stream?: ReadStreamDefinition }) {
);
}
function ChildStreamList({ stream }: { stream?: ReadStreamDefinition }) {
function ChildStreamList({ definition }: { definition?: IngestStreamGetResponse }) {
const {
dependencies: {
start: {
@ -305,15 +307,15 @@ function ChildStreamList({ stream }: { stream?: ReadStreamDefinition }) {
);
const childDefinitions = useMemo(() => {
if (!stream) {
if (!definition) {
return [];
}
return streamsListFetch.value?.streams.filter(
(d) => isWiredStreamDefinition(d) && d.name.startsWith(stream.name as string)
(d) => isWiredStreamDefinition(d) && d.name.startsWith(definition.stream.name)
);
}, [stream, streamsListFetch.value?.streams]);
}, [definition, streamsListFetch.value?.streams]);
if (stream && childDefinitions?.length === 1) {
if (definition && childDefinitions?.length === 1) {
return (
<EuiFlexItem grow>
<EuiFlexGroup alignItems="center" justifyContent="center">
@ -342,7 +344,7 @@ function ChildStreamList({ stream }: { stream?: ReadStreamDefinition }) {
iconType="plusInCircle"
href={router.link('/{key}/management/{subtab}', {
path: {
key: stream?.name as string,
key: definition?.stream.name,
subtab: 'route',
},
})}

View file

@ -42,6 +42,7 @@ import {
RoutingDefinition,
IngestUpsertRequest,
getAncestorsAndSelf,
WiredStreamGetResponse,
} from '@kbn/streams-schema';
import { useUnsavedChangesPrompt } from '@kbn/unsaved-changes-prompt';
import { AbortableAsyncState } from '@kbn/observability-utils-browser/hooks/use_abortable_async';
@ -74,7 +75,7 @@ function useRoutingState({
definition,
toasts,
}: {
definition?: ReadStreamDefinition;
definition?: WiredStreamGetResponse;
toasts: IToasts;
}) {
const [lastDisplayedToast, setLastDisplayedToast] = React.useState<Toast | undefined>();
@ -157,7 +158,7 @@ export function StreamDetailRouting({
definition,
refreshDefinition,
}: {
definition?: ReadStreamDefinition;
definition?: WiredStreamGetResponse;
refreshDefinition: () => void;
}) {
const { appParams, core } = useKibana();
@ -287,7 +288,7 @@ function ControlBar({
routingAppState,
refreshDefinition,
}: {
definition: ReadStreamDefinition;
definition: WiredStreamGetResponse;
routingAppState: ReturnType<typeof useRoutingState>;
refreshDefinition: () => void;
}) {
@ -326,7 +327,7 @@ function ControlBar({
signal,
params: {
path: {
id: definition.name,
id: definition.stream.name,
},
body: {
if: emptyEqualsToAlways(routingAppState.childUnderEdit.child.if),
@ -345,7 +346,7 @@ function ControlBar({
}
const childUnderEdit = routingAppState.childUnderEdit?.child;
const { name, stream } = definition;
const { stream } = definition;
const routing = routingAppState.childStreams.map((child) =>
child.destination === childUnderEdit?.destination ? childUnderEdit : child
@ -362,7 +363,7 @@ function ControlBar({
signal,
params: {
path: {
id: name,
id: stream.name,
},
body: request,
},
@ -483,7 +484,7 @@ function PreviewPanel({
definition,
routingAppState,
}: {
definition: ReadStreamDefinition;
definition: WiredStreamGetResponse;
routingAppState: ReturnType<typeof useRoutingState>;
}) {
const {
@ -513,7 +514,7 @@ function PreviewPanel({
signal,
params: {
path: {
id: definition.name,
id: definition.stream.name,
},
body: {
if: emptyEqualsToAlways(debouncedChildUnderEdit.child.if),
@ -688,7 +689,7 @@ function ChildStreamList({
draggingChildStream,
},
}: {
definition: ReadStreamDefinition;
definition: WiredStreamGetResponse;
routingAppState: ReturnType<typeof useRoutingState>;
availableStreams: string[];
}) {
@ -801,7 +802,7 @@ function ChildStreamList({
selectChildUnderEdit({
isNew: true,
child: {
destination: `${definition.name}.child`,
destination: `${definition.stream.name}.child`,
if: cloneDeep(EMPTY_EQUALS_CONDITION),
},
});
@ -819,31 +820,35 @@ function ChildStreamList({
);
}
function CurrentStreamEntry({ definition }: { definition: ReadStreamDefinition }) {
function CurrentStreamEntry({ definition }: { definition: WiredStreamGetResponse }) {
const router = useStreamsAppRouter();
const breadcrumbs: EuiBreadcrumb[] = getAncestorsAndSelf(definition.name).map((parentId) => {
const isBreadcrumbsTail = parentId === definition.name;
const breadcrumbs: EuiBreadcrumb[] = getAncestorsAndSelf(definition.stream.name).map(
(parentId) => {
const isBreadcrumbsTail = parentId === definition.stream.name;
return {
text: parentId,
href: isBreadcrumbsTail
? undefined
: router.link('/{key}/{tab}/{subtab}', {
path: {
key: parentId,
tab: 'management',
subtab: 'route',
},
}),
};
});
return {
text: parentId,
href: isBreadcrumbsTail
? undefined
: router.link('/{key}/{tab}/{subtab}', {
path: {
key: parentId,
tab: 'management',
subtab: 'route',
},
}),
};
}
);
return (
<>
{!isRoot(definition.name) && <EuiBreadcrumbs breadcrumbs={breadcrumbs} truncate={false} />}
{!isRoot(definition.stream.name) && (
<EuiBreadcrumbs breadcrumbs={breadcrumbs} truncate={false} />
)}
<EuiFlexItem grow={false}>
<EuiPanel hasShadow={false} hasBorder paddingSize="s">
<EuiText size="s">{definition.name}</EuiText>
<EuiText size="s">{definition.stream.name}</EuiText>
<EuiText size="xs" color="subdued">
{i18n.translate('xpack.streams.streamDetailRouting.currentStream', {
defaultMessage: 'Current stream',

View file

@ -23,11 +23,7 @@ import type {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import useToggle from 'react-use/lib/useToggle';
import {
isRootStreamDefinition,
isWiredReadStream,
ReadStreamDefinition,
} from '@kbn/streams-schema';
import { isRootStreamDefinition, WiredStreamGetResponse } from '@kbn/streams-schema';
import { FieldType } from './field_type';
import { FieldStatusBadge } from './field_status';
import { FieldEntry, SchemaEditorEditingState } from './hooks/use_editing_state';
@ -36,7 +32,7 @@ import { FieldParent } from './field_parent';
import { SchemaEditorQueryAndFiltersState } from './hooks/use_query_and_filters';
interface FieldsTableContainerProps {
definition: ReadStreamDefinition;
definition: WiredStreamGetResponse;
unmappedFieldsResult?: string[];
isLoadingUnmappedFields: boolean;
query?: Query;
@ -101,15 +97,13 @@ export const FieldsTableContainer = ({
}, [inheritedFields, query]);
const mappedFields = useMemo(() => {
if (isWiredReadStream(definition)) {
return Object.entries(definition.stream.ingest.wired.fields).map(([name, field]) => ({
name,
type: field.type,
format: field.format,
parent: definition.name,
status: 'mapped' as const,
}));
}
return Object.entries(definition.stream.ingest.wired.fields).map(([name, field]) => ({
name,
type: field.type,
format: field.format,
parent: definition.stream.name,
status: 'mapped' as const,
}));
return [];
}, [definition]);
@ -124,11 +118,11 @@ export const FieldsTableContainer = ({
return unmappedFieldsResult
? unmappedFieldsResult.map((field) => ({
name: field,
parent: definition.name,
parent: definition.stream.name,
status: 'unmapped' as const,
}))
: [];
}, [definition.name, unmappedFieldsResult]);
}, [definition.stream.name, unmappedFieldsResult]);
const filteredUnmappedFields = useMemo(() => {
if (!unmappedFieldsResult) return [];
@ -172,7 +166,7 @@ export const FieldsTableContainer = ({
};
interface FieldsTableProps {
definition: ReadStreamDefinition;
definition: WiredStreamGetResponse;
fields: FieldEntry[];
editingState: SchemaEditorEditingState;
unpromotingState: SchemaEditorUnpromotingState;
@ -326,7 +320,10 @@ const FieldsTable = ({ definition, fields, editingState, unpromotingState }: Fie
return <FieldType type={fieldType} />;
} else if (columnId === 'parent') {
return (
<FieldParent parent={field.parent} linkEnabled={field.parent !== definition.name} />
<FieldParent
parent={field.parent}
linkEnabled={field.parent !== definition.stream.name}
/>
);
} else if (columnId === 'status') {
return <FieldStatusBadge status={field.status} />;

View file

@ -19,7 +19,7 @@ import {
} from '@elastic/eui';
import React from 'react';
import { i18n } from '@kbn/i18n';
import { ReadStreamDefinition } from '@kbn/streams-schema';
import { WiredStreamGetResponse } from '@kbn/streams-schema';
import { SchemaEditorEditingState } from '../hooks/use_editing_state';
import { ChildrenAffectedCallout } from './children_affected_callout';
import { SamplePreviewTable } from './sample_preview_table';
@ -27,7 +27,7 @@ import { FieldSummary } from './field_summary';
export type SchemaEditorFlyoutProps = {
streamsRepositoryClient: StreamsRepositoryClient;
definition: ReadStreamDefinition;
definition: WiredStreamGetResponse;
} & SchemaEditorEditingState;
export const SchemaEditorFlyout = (props: SchemaEditorFlyoutProps) => {

View file

@ -10,7 +10,7 @@ import { StreamsRepositoryClient } from '@kbn/streams-plugin/public/api';
import { css } from '@emotion/react';
import { i18n } from '@kbn/i18n';
import { EuiCallOut } from '@elastic/eui';
import { NamedFieldDefinitionConfig, ReadStreamDefinition } from '@kbn/streams-schema';
import { NamedFieldDefinitionConfig, WiredStreamGetResponse } from '@kbn/streams-schema';
import { getFormattedError } from '../../../util/errors';
import { useStreamsAppFetch } from '../../../hooks/use_streams_app_fetch';
import { PreviewTable } from '../../preview_table';
@ -18,7 +18,7 @@ import { isFullFieldDefinition } from '../hooks/use_editing_state';
import { LoadingPanel } from '../../loading_panel';
interface SamplePreviewTableProps {
definition: ReadStreamDefinition;
definition: WiredStreamGetResponse;
nextFieldDefinition?: Partial<NamedFieldDefinitionConfig>;
streamsRepositoryClient: StreamsRepositoryClient;
}
@ -45,7 +45,7 @@ const SamplePreviewTableContent = ({
signal,
params: {
path: {
id: definition.name,
id: definition.stream.name,
},
body: {
field_definitions: [nextFieldDefinition],
@ -53,7 +53,7 @@ const SamplePreviewTableContent = ({
},
});
},
[definition.name, nextFieldDefinition, streamsRepositoryClient],
[definition.stream.name, nextFieldDefinition, streamsRepositoryClient],
{
disableToastOnError: true,
}

View file

@ -5,11 +5,7 @@
* 2.0.
*/
import {
ReadStreamDefinition,
NamedFieldDefinitionConfig,
isWiredReadStream,
} from '@kbn/streams-schema';
import { NamedFieldDefinitionConfig, WiredStreamGetResponse } from '@kbn/streams-schema';
import { StreamsRepositoryClient } from '@kbn/streams-plugin/public/api';
import { useCallback, useMemo, useState } from 'react';
import useToggle from 'react-use/lib/useToggle';
@ -39,7 +35,7 @@ export const useEditingState = ({
toastsService,
}: {
streamsRepositoryClient: StreamsRepositoryClient;
definition: ReadStreamDefinition;
definition: WiredStreamGetResponse;
refreshDefinition: () => void;
refreshUnmappedFields: () => void;
toastsService: ToastsStart;
@ -95,8 +91,7 @@ export const useEditingState = ({
const saveChanges = useMemo(() => {
return selectedField &&
isFullFieldDefinition(nextFieldDefinition) &&
hasChanges(selectedField, nextFieldDefinition) &&
isWiredReadStream(definition)
hasChanges(selectedField, nextFieldDefinition)
? async () => {
toggleIsSaving(true);
try {
@ -104,7 +99,7 @@ export const useEditingState = ({
signal: abortController.signal,
params: {
path: {
id: definition.name,
id: definition.stream.name,
},
body: {
ingest: {

View file

@ -11,8 +11,8 @@ import useToggle from 'react-use/lib/useToggle';
import { useAbortController } from '@kbn/observability-utils-browser/hooks/use_abort_controller';
import { ToastsStart } from '@kbn/core-notifications-browser';
import { i18n } from '@kbn/i18n';
import { WiredReadStreamDefinition } from '@kbn/streams-schema';
import { omit } from 'lodash';
import { WiredStreamGetResponse } from '@kbn/streams-schema';
export type SchemaEditorUnpromotingState = ReturnType<typeof useUnpromotingState>;
@ -24,7 +24,7 @@ export const useUnpromotingState = ({
toastsService,
}: {
streamsRepositoryClient: StreamsRepositoryClient;
definition: WiredReadStreamDefinition;
definition: WiredStreamGetResponse;
refreshDefinition: () => void;
refreshUnmappedFields: () => void;
toastsService: ToastsStart;
@ -47,7 +47,7 @@ export const useUnpromotingState = ({
signal: abortController.signal,
params: {
path: {
id: definition.name,
id: definition.stream.name,
},
body: {
ingest: {
@ -81,8 +81,8 @@ export const useUnpromotingState = ({
}
}, [
abortController.signal,
definition.name,
definition.stream.ingest,
definition.stream.name,
refreshDefinition,
refreshUnmappedFields,
selectedField,

View file

@ -7,7 +7,7 @@
import React, { useEffect } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiProgress, EuiPortal } from '@elastic/eui';
import { css } from '@emotion/css';
import { WiredReadStreamDefinition } from '@kbn/streams-schema';
import { WiredStreamGetResponse } from '@kbn/streams-schema';
import { useEditingState } from './hooks/use_editing_state';
import { SchemaEditorFlyout } from './flyout';
import { useKibana } from '../../hooks/use_kibana';
@ -21,7 +21,7 @@ import { useQueryAndFilters } from './hooks/use_query_and_filters';
import { FieldStatusFilterGroup } from './filters/status_filter_group';
interface SchemaEditorProps {
definition?: WiredReadStreamDefinition;
definition?: WiredStreamGetResponse;
refreshDefinition: () => void;
isLoadingDefinition: boolean;
}
@ -59,12 +59,12 @@ const Content = ({
signal,
params: {
path: {
id: definition.name,
id: definition.stream.name,
},
},
});
},
[definition.name, streamsRepositoryClient]
[definition.stream.name, streamsRepositoryClient]
);
const editingState = useEditingState({
@ -88,7 +88,7 @@ const Content = ({
// If the definition changes (e.g. navigating to parent stream), reset the entire editing state.
useEffect(() => {
reset();
}, [definition.name, reset]);
}, [definition.stream.name, reset]);
return (
<EuiFlexItem>

View file

@ -5,7 +5,6 @@
* 2.0.
*/
import { i18n } from '@kbn/i18n';
import { isWiredStreamGetResponse } from '@kbn/streams-schema';
import React from 'react';
import { useKibana } from '../../hooks/use_kibana';
import { useStreamsAppFetch } from '../../hooks/use_streams_app_fetch';
@ -37,43 +36,14 @@ export function StreamDetailView() {
loading,
} = useStreamsAppFetch(
({ signal }) => {
return streamsRepositoryClient
.fetch('GET /api/streams/{id}', {
signal,
params: {
path: {
id: key,
},
return streamsRepositoryClient.fetch('GET /api/streams/{id}', {
signal,
params: {
path: {
id: key,
},
})
.then((response) => {
if (isWiredStreamGetResponse(response)) {
return {
dashboards: response.dashboards,
inherited_fields: response.inherited_fields,
elasticsearch_assets: [],
effective_lifecycle: response.effective_lifecycle,
name: key,
stream: {
name: key,
...response.stream,
},
};
}
return {
dashboards: response.dashboards,
elasticsearch_assets: response.elasticsearch_assets,
inherited_fields: {},
effective_lifecycle: response.effective_lifecycle,
name: key,
data_stream_exists: response.data_stream_exists,
stream: {
name: key,
...response.stream,
},
};
});
},
});
},
[streamsRepositoryClient, key]
);

View file

@ -113,6 +113,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
expect(dashboards).to.eql([]);
expect(stream).to.eql({
name: TEST_STREAM_NAME,
ingest: {
lifecycle: { inherit: {} },
processing: [

View file

@ -9,7 +9,7 @@ import expect from '@kbn/expect';
import {
StreamUpsertRequest,
StreamGetResponse,
WiredReadStreamDefinition,
WiredStreamGetResponse,
} from '@kbn/streams-schema';
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
import {
@ -187,7 +187,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
},
});
expect(
(logsDeeplyNestedStreamname.body as WiredReadStreamDefinition).stream.ingest.wired.fields
(logsDeeplyNestedStreamname.body as WiredStreamGetResponse).stream.ingest.wired.fields
).to.eql({
field2: {
type: 'keyword',

View file

@ -10,7 +10,6 @@ import {
IngestStreamEffectiveLifecycle,
IngestStreamLifecycle,
IngestStreamUpsertRequest,
WiredReadStreamDefinition,
WiredStreamGetResponse,
isDslLifecycle,
isIlmLifecycle,
@ -103,11 +102,9 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
expect(response).to.have.property('acknowledged', true);
const updatedRootDefinition = await getStream(apiClient, 'logs');
expect((updatedRootDefinition as WiredReadStreamDefinition).stream.ingest.lifecycle).to.eql(
{
dsl: { data_retention: '999d' },
}
);
expect((updatedRootDefinition as WiredStreamGetResponse).stream.ingest.lifecycle).to.eql({
dsl: { data_retention: '999d' },
});
expect(updatedRootDefinition.effective_lifecycle).to.eql({
dsl: { data_retention: '999d' },
from: 'logs',