Skip to content

Commit 528e90f

Browse files
[Streams 🌊] Bug fixing and refactor routing UI (elastic#219281)
## 📓 Summary This work is a refactor of the routing state management and some components, after finding various inconsistent behaviours that we commented on offline. Most of the problems were due to the complicated interaction logic on the routing rules, which is going to become even more complex with the planned features we want to add on the partititiong page. The refactor fixes most of those issues, although it's not complete: - The samples fetching logic has not been moved but deserves a double check, the async searches heavily impact the Kibana server, and we should better control unintended requests. --------- Co-authored-by: Joe Reuter <johannes.reuter@elastic.co>
1 parent 5a4cd4d commit 528e90f

25 files changed

Lines changed: 1374 additions & 878 deletions

File tree

x-pack/platform/packages/shared/kbn-streams-schema/src/models/ingest/base.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { NonEmptyString } from '@kbn/zod-helpers';
1010
import { StreamDefinitionBase } from '../base';
1111
import { FieldDefinition, fieldDefinitionSchema } from './fields';
1212
import { ProcessorDefinition, processorDefinitionSchema } from './processors';
13-
import { RoutingDefinition, routingDefinitionSchema } from './routing';
13+
import { RoutingDefinition, routingDefinitionListSchema } from './routing';
1414
import { IngestStreamLifecycle, ingestStreamLifecycleSchema } from './lifecycle';
1515

1616
interface IngestBase {
@@ -64,7 +64,7 @@ const wiredIngestSchema: z.Schema<WiredIngest> = z.intersection(
6464
z.object({
6565
wired: z.object({
6666
fields: fieldDefinitionSchema,
67-
routing: z.array(routingDefinitionSchema),
67+
routing: routingDefinitionListSchema,
6868
}),
6969
})
7070
);

x-pack/platform/packages/shared/kbn-streams-schema/src/models/ingest/routing/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ export const routingDefinitionSchema: z.Schema<RoutingDefinition> = z.object({
1818
destination: NonEmptyString,
1919
if: conditionSchema,
2020
});
21+
22+
export const routingDefinitionListSchema: z.Schema<RoutingDefinition[]> =
23+
z.array(routingDefinitionSchema);

x-pack/platform/plugins/private/translations/translations/fr-FR.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44785,10 +44785,8 @@
4478544785
"xpack.streams.streamDetailRouting.deleteModalTitle": "Voulez-vous vraiment supprimer ce flux de données ?",
4478644786
"xpack.streams.streamDetailRouting.edit": "Modifier",
4478744787
"xpack.streams.streamDetailRouting.name": "Nom du flux",
44788-
"xpack.streams.streamDetailRouting.numberChildren": "{children, plural, one {# enfant} other {# enfants}}",
4478944788
"xpack.streams.streamDetailRouting.remove": "Supprimer",
4479044789
"xpack.streams.streamDetailRouting.rules.header": "Règles de routage",
44791-
"xpack.streams.streamDetailRouting.save": "Enregistrer",
4479244790
"xpack.streams.streamDetailRouting.saved": "Flux enregistré",
4479344791
"xpack.streams.streamDetailRouting.view": "Ouvrir le flux dans un nouvel onglet",
4479444792
"xpack.streams.streamDetailSchemaEditor.ecsRecommendationLoadingText": "Chargement...",

x-pack/platform/plugins/private/translations/translations/ja-JP.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44752,10 +44752,8 @@
4475244752
"xpack.streams.streamDetailRouting.deleteModalTitle": "このデータストリームを削除しますか?",
4475344753
"xpack.streams.streamDetailRouting.edit": "編集",
4475444754
"xpack.streams.streamDetailRouting.name": "ストリーム名",
44755-
"xpack.streams.streamDetailRouting.numberChildren": "{children, plural, other {#個の子}}",
4475644755
"xpack.streams.streamDetailRouting.remove": "削除",
4475744756
"xpack.streams.streamDetailRouting.rules.header": "ルーティングルール",
44758-
"xpack.streams.streamDetailRouting.save": "保存",
4475944757
"xpack.streams.streamDetailRouting.saved": "ストリームが保存されました",
4476044758
"xpack.streams.streamDetailRouting.view": "新しいタブでストリームを開く",
4476144759
"xpack.streams.streamDetailSchemaEditor.ecsRecommendationLoadingText": "読み込み中...",

x-pack/platform/plugins/private/translations/translations/zh-CN.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44822,10 +44822,8 @@
4482244822
"xpack.streams.streamDetailRouting.deleteModalTitle": "是否确定要删除此数据流?",
4482344823
"xpack.streams.streamDetailRouting.edit": "编辑",
4482444824
"xpack.streams.streamDetailRouting.name": "流名称",
44825-
"xpack.streams.streamDetailRouting.numberChildren": "{children, plural, other {# 个子项}}",
4482644825
"xpack.streams.streamDetailRouting.remove": "移除",
4482744826
"xpack.streams.streamDetailRouting.rules.header": "正在路由规则",
44828-
"xpack.streams.streamDetailRouting.save": "保存",
4482944827
"xpack.streams.streamDetailRouting.saved": "流已保存",
4483044828
"xpack.streams.streamDetailRouting.view": "在新选项卡中打开流",
4483144829
"xpack.streams.streamDetailSchemaEditor.ecsRecommendationLoadingText": "正在加载……",

x-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_routing/child_stream_list.tsx

Lines changed: 51 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,38 @@ import {
1414
EuiDraggable,
1515
EuiButton,
1616
EuiToolTip,
17+
euiDragDropReorder,
18+
DragDropContextProps,
1719
} from '@elastic/eui';
1820
import { i18n } from '@kbn/i18n';
1921
import { css } from '@emotion/css';
20-
import { cloneDeep } from 'lodash';
2122
import React from 'react';
22-
import { ALWAYS_CONDITION } from '../../../util/condition';
2323
import { NestedView } from '../../nested_view';
24-
import { useRoutingStateContext } from './hooks/routing_state';
2524
import { CurrentStreamEntry } from './current_stream_entry';
2625
import { NewRoutingStreamEntry } from './new_routing_stream_entry';
2726
import { RoutingStreamEntry } from './routing_stream_entry';
27+
import {
28+
useStreamRoutingEvents,
29+
useStreamsRoutingSelector,
30+
} from './state_management/stream_routing_state_machine';
2831

2932
export function ChildStreamList({ availableStreams }: { availableStreams: string[] }) {
30-
const {
31-
routingAppState: {
32-
childUnderEdit,
33-
selectChildUnderEdit,
34-
childStreams,
35-
onChildStreamDragEnd,
36-
onChildStreamDragStart,
37-
draggingChildStream,
38-
hasChildStreamsOrderChanged,
39-
},
40-
definition,
41-
} = useRoutingStateContext();
33+
const { changeRule, createNewRule, editRule, reorderRules } = useStreamRoutingEvents();
34+
const routingSnapshot = useStreamsRoutingSelector((snapshot) => snapshot);
35+
36+
const { currentRuleId, definition, routing } = routingSnapshot.context;
37+
const canCreateRoutingRules = routingSnapshot.can({ type: 'routingRule.create' });
38+
const canReorderRoutingRules = routingSnapshot.can({ type: 'routingRule.reorder', routing });
39+
const canManageRoutingRules = definition.privileges.manage;
40+
const shouldDisplayCreateButton = definition.privileges.simulate;
41+
42+
const handlerItemDrag: DragDropContextProps['onDragEnd'] = ({ source, destination }) => {
43+
if (source && destination) {
44+
const items = euiDragDropReorder(routing, source.index, destination.index);
45+
reorderRules(items);
46+
}
47+
};
48+
4249
return (
4350
<EuiFlexGroup
4451
direction="column"
@@ -61,11 +68,11 @@ export function ChildStreamList({ availableStreams }: { availableStreams: string
6168
defaultMessage: 'Routing rules',
6269
})}
6370
</EuiText>
64-
{definition.privileges.simulate && (
71+
{shouldDisplayCreateButton && (
6572
<EuiFlexItem grow={false}>
6673
<EuiToolTip
6774
content={
68-
!definition.privileges.manage
75+
!canManageRoutingRules
6976
? i18n.translate('xpack.streams.streamDetailRouting.rules.onlySimulate', {
7077
defaultMessage:
7178
"You don't have sufficient privileges to create new streams, only simulate.",
@@ -77,15 +84,8 @@ export function ChildStreamList({ availableStreams }: { availableStreams: string
7784
iconType="plus"
7885
size="s"
7986
data-test-subj="streamsAppStreamDetailRoutingAddRuleButton"
80-
onClick={() => {
81-
selectChildUnderEdit({
82-
isNew: true,
83-
child: {
84-
destination: `${definition.stream.name}.child`,
85-
if: cloneDeep(ALWAYS_CONDITION),
86-
},
87-
});
88-
}}
87+
onClick={createNewRule}
88+
disabled={!canCreateRoutingRules}
8989
>
9090
{i18n.translate('xpack.streams.streamDetailRouting.addRule', {
9191
defaultMessage: 'Create child stream',
@@ -104,56 +104,40 @@ export function ChildStreamList({ availableStreams }: { availableStreams: string
104104
`}
105105
>
106106
<CurrentStreamEntry definition={definition} />
107-
<EuiDragDropContext onDragEnd={onChildStreamDragEnd} onDragStart={onChildStreamDragStart}>
107+
<EuiDragDropContext onDragEnd={handlerItemDrag}>
108108
<EuiDroppable droppableId="routing_children_reordering" spacing="none">
109109
<EuiFlexGroup direction="column" gutterSize="xs">
110-
{childStreams.map((child, i) => (
111-
<EuiFlexItem key={`${child.destination}-${i}-flex-item`} grow={false}>
110+
{routing.map((routingRule, pos) => (
111+
<EuiFlexItem key={routingRule.id} grow={false}>
112112
<EuiDraggable
113-
key={child.destination}
114-
index={i}
115-
isDragDisabled={!definition.privileges.manage}
116-
draggableId={child.destination}
113+
index={pos}
114+
isDragDisabled={!canReorderRoutingRules}
115+
draggableId={routingRule.id}
117116
hasInteractiveChildren={true}
118117
customDragHandle={true}
119118
spacing="none"
120119
>
121-
{(provided) => (
120+
{(provided, snapshot) => (
122121
<NestedView
123-
key={i}
124-
last={!childUnderEdit?.isNew && i === childStreams.length - 1}
125-
isBeingDragged={draggingChildStream === child.destination}
122+
last={pos === routing.length - 1}
123+
isBeingDragged={snapshot.isDragging}
126124
>
127-
<RoutingStreamEntry
128-
draggableProvided={provided}
129-
disableEditButton={
130-
hasChildStreamsOrderChanged || !definition.privileges.manage
131-
}
132-
child={
133-
!childUnderEdit?.isNew &&
134-
child.destination === childUnderEdit?.child.destination
135-
? childUnderEdit.child
136-
: child
137-
}
138-
edit={
139-
!childUnderEdit?.isNew &&
140-
child.destination === childUnderEdit?.child.destination
141-
}
142-
onEditStateChange={() => {
143-
if (child.destination === childUnderEdit?.child.destination) {
144-
selectChildUnderEdit(undefined);
145-
} else {
146-
selectChildUnderEdit({ isNew: false, child });
147-
}
148-
}}
149-
onChildChange={(newChild) => {
150-
selectChildUnderEdit({
151-
isNew: false,
152-
child: newChild,
153-
});
154-
}}
155-
availableStreams={availableStreams}
156-
/>
125+
{routingRule.isNew ? (
126+
<NewRoutingStreamEntry />
127+
) : (
128+
<RoutingStreamEntry
129+
availableStreams={availableStreams}
130+
draggableProvided={provided}
131+
isEditing={currentRuleId === routingRule.id}
132+
isEditingEnabled={routingSnapshot.can({
133+
type: 'routingRule.edit',
134+
id: routingRule.id,
135+
})}
136+
onChange={changeRule}
137+
onEditIconClick={editRule}
138+
routingRule={routingRule}
139+
/>
140+
)}
157141
</NestedView>
158142
)}
159143
</EuiDraggable>
@@ -162,23 +146,6 @@ export function ChildStreamList({ availableStreams }: { availableStreams: string
162146
</EuiFlexGroup>
163147
</EuiDroppable>
164148
</EuiDragDropContext>
165-
{childUnderEdit?.isNew && (
166-
<NestedView last>
167-
<NewRoutingStreamEntry
168-
child={childUnderEdit.child}
169-
onChildChange={(newChild) => {
170-
if (!newChild) {
171-
selectChildUnderEdit(undefined);
172-
return;
173-
}
174-
selectChildUnderEdit({
175-
isNew: true,
176-
child: newChild,
177-
});
178-
}}
179-
/>
180-
</NestedView>
181-
)}
182149
</EuiFlexGroup>
183150
</EuiFlexGroup>
184151
);

0 commit comments

Comments
 (0)