Skip to content

Commit

Permalink
[Streams] Partitioning page toasts UX improvement (elastic#206571)
Browse files Browse the repository at this point in the history
## Summary

Just a UX improvement to implement this:
elastic#206116 (comment)
(elastic#206116 was merged already).
  • Loading branch information
Kerry350 authored Jan 15, 2025
1 parent 0c4c8aa commit a4c1c20
Showing 1 changed file with 50 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
import { useUnsavedChangesPrompt } from '@kbn/unsaved-changes-prompt';
import { AbortableAsyncState } from '@kbn/observability-utils-browser/hooks/use_abortable_async';
import { DraggableProvided } from '@hello-pangea/dnd';
import { IToasts, Toast } from '@kbn/core/public';
import { toMountPoint } from '@kbn/react-kibana-mount';
import { useKibana } from '../../hooks/use_kibana';
import { useStreamsAppFetch } from '../../hooks/use_streams_app_fetch';
Expand All @@ -57,10 +58,31 @@ import { PreviewTable } from '../preview_table';
import { StreamDeleteModal } from '../stream_delete_modal';
import { AssetImage } from '../asset_image';

function useRoutingState({ definition }: { definition?: ReadStreamDefinition }) {
const [childUnderEdit, setChildUnderEdit] = React.useState<
{ isNew: boolean; child: StreamChild } | undefined
>();
interface ChildUnderEdit {
isNew: boolean;
child: StreamChild;
}

function useRoutingState({
definition,
toasts,
}: {
definition?: ReadStreamDefinition;
toasts: IToasts;
}) {
const [lastDisplayedToast, setLastDisplayedToast] = React.useState<Toast | undefined>();

const [childUnderEdit, setChildUnderEdit] = React.useState<ChildUnderEdit | undefined>();

const selectChildUnderEdit = useCallback(
(child: ChildUnderEdit | undefined) => {
if (lastDisplayedToast) {
toasts.remove(lastDisplayedToast.id);
}
setChildUnderEdit(child);
},
[lastDisplayedToast, toasts]
);

// Child streams: either represents the child streams as they are, or the new order from drag and drop.
const [childStreams, setChildStreams] = React.useState<
Expand All @@ -83,14 +105,17 @@ function useRoutingState({ definition }: { definition?: ReadStreamDefinition })

const onChildStreamDragEnd = useCallback(
(event: DropResult) => {
if (lastDisplayedToast) {
toasts.remove(lastDisplayedToast.id);
}
setDraggingChildStream(undefined);
if (typeof event.source.index === 'number' && typeof event.destination?.index === 'number') {
setChildStreams([
...euiDragDropReorder(childStreams, event.source.index, event.destination.index),
]);
}
},
[childStreams]
[childStreams, lastDisplayedToast, toasts]
);

const cancelChanges = useCallback(() => {
Expand All @@ -104,9 +129,10 @@ function useRoutingState({ definition }: { definition?: ReadStreamDefinition })
const [showDeleteModal, setShowDeleteModal] = React.useState(false);

return {
setLastDisplayedToast,
debouncedChildUnderEdit,
childUnderEdit,
setChildUnderEdit,
selectChildUnderEdit,
saveInProgress,
setSaveInProgress,
showDeleteModal,
Expand All @@ -129,7 +155,7 @@ export function StreamDetailRouting({
}) {
const { appParams, core } = useKibana();
const theme = useEuiTheme().euiTheme;
const routingAppState = useRoutingState({ definition });
const routingAppState = useRoutingState({ definition, toasts: core.notifications.toasts });

const {
dependencies: {
Expand Down Expand Up @@ -174,7 +200,7 @@ export function StreamDetailRouting({
{routingAppState.showDeleteModal && routingAppState.childUnderEdit && (
<StreamDeleteModal
closeModal={closeModal}
clearChildUnderEdit={() => routingAppState.setChildUnderEdit(undefined)}
clearChildUnderEdit={() => routingAppState.selectChildUnderEdit(undefined)}
refreshDefinition={refreshDefinition}
id={routingAppState.childUnderEdit.child.name}
availableStreams={availableStreams}
Expand Down Expand Up @@ -349,7 +375,7 @@ function ControlBar({
}

routingAppState.setSaveInProgress(false);
notifications.toasts.addSuccess({
const toast = notifications.toasts.addSuccess({
title: i18n.translate('xpack.streams.streamDetailRouting.saved', {
defaultMessage: 'Stream saved',
}),
Expand All @@ -376,16 +402,18 @@ function ControlBar({
core
),
});
routingAppState.setChildUnderEdit(undefined);
routingAppState.setLastDisplayedToast(toast);
routingAppState.selectChildUnderEdit(undefined);
refreshDefinition();
} catch (error) {
routingAppState.setSaveInProgress(false);
notifications.toasts.addError(error, {
const toast = notifications.toasts.addError(error, {
title: i18n.translate('xpack.streams.failedToSave', {
defaultMessage: 'Failed to save',
}),
toastMessage: 'body' in error ? error.body.message : error.message,
});
routingAppState.setLastDisplayedToast(toast);
}
}

Expand Down Expand Up @@ -640,7 +668,7 @@ function ChildStreamList({
availableStreams,
routingAppState: {
childUnderEdit,
setChildUnderEdit,
selectChildUnderEdit,
childStreams,
onChildStreamDragEnd,
onChildStreamDragStart,
Expand Down Expand Up @@ -706,13 +734,13 @@ function ChildStreamList({
edit={!childUnderEdit?.isNew && child.name === childUnderEdit?.child.name}
onEditStateChange={() => {
if (child.name === childUnderEdit?.child.name) {
setChildUnderEdit(undefined);
selectChildUnderEdit(undefined);
} else {
setChildUnderEdit({ isNew: false, child });
selectChildUnderEdit({ isNew: false, child });
}
}}
onChildChange={(newChild) => {
setChildUnderEdit({
selectChildUnderEdit({
isNew: false,
child: newChild,
});
Expand All @@ -733,10 +761,10 @@ function ChildStreamList({
child={childUnderEdit.child}
onChildChange={(newChild) => {
if (!newChild) {
setChildUnderEdit(undefined);
selectChildUnderEdit(undefined);
return;
}
setChildUnderEdit({
selectChildUnderEdit({
isNew: true,
child: newChild,
});
Expand All @@ -750,7 +778,7 @@ function ChildStreamList({
iconType="plus"
data-test-subj="streamsAppStreamDetailRoutingAddRuleButton"
onClick={() => {
setChildUnderEdit({
selectChildUnderEdit({
isNew: true,
child: {
name: `${definition.name}.child`,
Expand Down Expand Up @@ -839,7 +867,10 @@ function RoutingStreamEntry({
color="transparent"
paddingSize="s"
{...draggableProvided.dragHandleProps}
aria-label="Drag Handle"
aria-label={i18n.translate(
'xpack.streams.routingStreamEntry.euiPanel.dragHandleLabel',
{ defaultMessage: 'Drag Handle' }
)}
>
<EuiIcon type="grab" />
</EuiPanel>
Expand Down

0 comments on commit a4c1c20

Please sign in to comment.