Skip to content

Commit

Permalink
[APM] Service groups: Add EuiTour steps for assisting users in creati…
Browse files Browse the repository at this point in the history
…ng their first service group and provide guidance on the navigation changes (elastic#128068)
  • Loading branch information
cauemarcondes authored and patrykkopycinski committed Mar 23, 2022
1 parent 7d29e42 commit cf082dd
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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 { EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { ServiceGroupsTour } from '../service_groups_tour';
import { useServiceGroupsTour } from '../use_service_groups_tour';

interface Props {
onClick: () => void;
}

export function CreateButton({ onClick }: Props) {
const { tourEnabled, dismissTour } = useServiceGroupsTour('createGroup');
return (
<ServiceGroupsTour
tourEnabled={tourEnabled}
dismissTour={dismissTour}
title={i18n.translate('xpack.apm.serviceGroups.tour.createGroups.title', {
defaultMessage: 'Introducing service groups',
})}
content={i18n.translate(
'xpack.apm.serviceGroups.tour.createGroups.content',
{
defaultMessage:
'Group services together to build curated inventory views that remove noise and simplify investigations across services. Groups are Kibana space-specific and available for any users with appropriate access.',
}
)}
>
<EuiButton
iconType="plusInCircle"
onClick={() => {
dismissTour();
onClick();
}}
>
{i18n.translate('xpack.apm.serviceGroups.createGroupLabel', {
defaultMessage: 'Create group',
})}
</EuiButton>
</ServiceGroupsTour>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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 { EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { ServiceGroupsTour } from '../service_groups_tour';
import { useServiceGroupsTour } from '../use_service_groups_tour';

interface Props {
onClick: () => void;
}

export function EditButton({ onClick }: Props) {
const { tourEnabled, dismissTour } = useServiceGroupsTour('editGroup');
return (
<ServiceGroupsTour
tourEnabled={tourEnabled}
dismissTour={dismissTour}
title={i18n.translate('xpack.apm.serviceGroups.tour.editGroups.title', {
defaultMessage: 'Edit this service group',
})}
content={i18n.translate(
'xpack.apm.serviceGroups.tour.editGroups.content',
{
defaultMessage:
'Use the edit option to change the name, query, or details of this service group.',
}
)}
>
<EuiButton
iconType="pencil"
onClick={() => {
dismissTour();
onClick();
}}
>
{i18n.translate('xpack.apm.serviceGroups.editGroupLabel', {
defaultMessage: 'Edit group',
})}
</EuiButton>
</ServiceGroupsTour>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useState } from 'react';
import { useAnyOfApmParams } from '../../../../hooks/use_apm_params';
import { useFetcher } from '../../../../hooks/use_fetcher';
import { CreateButton } from './create_button';
import { EditButton } from './edit_button';
import { SaveGroupModal } from './save_modal';

export function ServiceGroupSaveButton() {
Expand All @@ -32,16 +32,18 @@ export function ServiceGroupSaveButton() {
);
const savedServiceGroup = data?.serviceGroup;

function onClick() {
setIsModalVisible((state) => !state);
}

return (
<>
<EuiButton
iconType={isGroupEditMode ? 'pencil' : 'plusInCircle'}
onClick={async () => {
setIsModalVisible((state) => !state);
}}
>
{isGroupEditMode ? EDIT_GROUP_LABEL : CREATE_GROUP_LABEL}
</EuiButton>
{isGroupEditMode ? (
<EditButton onClick={onClick} />
) : (
<CreateButton onClick={onClick} />
)}

{isModalVisible && (
<SaveGroupModal
savedServiceGroup={savedServiceGroup}
Expand All @@ -53,12 +55,3 @@ export function ServiceGroupSaveButton() {
</>
);
}

const CREATE_GROUP_LABEL = i18n.translate(
'xpack.apm.serviceGroups.createGroupLabel',
{ defaultMessage: 'Create group' }
);
const EDIT_GROUP_LABEL = i18n.translate(
'xpack.apm.serviceGroups.editGroupLabel',
{ defaultMessage: 'Edit group' }
);
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,26 @@ import {
ServiceGroup,
SERVICE_GROUP_COLOR_DEFAULT,
} from '../../../../../common/service_groups';
import { ServiceGroupsTour } from '../service_groups_tour';
import { useServiceGroupsTour } from '../use_service_groups_tour';

interface Props {
serviceGroup: ServiceGroup;
hideServiceCount?: boolean;
onClick?: () => void;
href?: string;
withTour?: boolean;
}

export function ServiceGroupsCard({
serviceGroup,
hideServiceCount = false,
onClick,
href,
withTour,
}: Props) {
const { tourEnabled, dismissTour } = useServiceGroupsTour('serviceGroupCard');

const cardProps: EuiCardProps = {
style: { width: 286, height: 186 },
icon: (
Expand Down Expand Up @@ -69,10 +75,39 @@ export function ServiceGroupsCard({
)}
</EuiFlexGroup>
),
onClick,
onClick: () => {
dismissTour();
if (onClick) {
onClick();
}
},
href,
};

if (withTour) {
return (
<EuiFlexItem key={serviceGroup.groupName}>
<ServiceGroupsTour
tourEnabled={tourEnabled}
dismissTour={dismissTour}
title={i18n.translate(
'xpack.apm.serviceGroups.tour.serviceGroups.title',
{ defaultMessage: 'All services group' }
)}
content={i18n.translate(
'xpack.apm.serviceGroups.tour.serviceGroups.content',
{
defaultMessage:
"Now that you've created a service group, your All services inventory has moved here. This group cannot be edited or removed.",
}
)}
>
<EuiCard layout="vertical" {...cardProps} />
</ServiceGroupsTour>
</EuiFlexItem>
);
}

return (
<EuiFlexItem key={serviceGroup.groupName}>
<EuiCard layout="vertical" {...cardProps} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export function ServiceGroupsListItems({ items }: Props) {
/>
))}
<ServiceGroupsCard
withTour
serviceGroup={{
groupName: i18n.translate(
'xpack.apm.serviceGroups.list.allServices.name',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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 { EuiButtonEmpty, EuiSpacer, EuiText, EuiTourStep } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import React from 'react';
import { ElasticDocsLink } from '../../shared/links/elastic_docs_link';

export type TourType = 'createGroup' | 'editGroup' | 'serviceGroupCard';

interface Props {
title: string;
content: string;
tourEnabled: boolean;
dismissTour: () => void;
children: React.ReactElement;
}

export function ServiceGroupsTour({
tourEnabled,
dismissTour,
title,
content,
children,
}: Props) {
return (
<EuiTourStep
content={
<>
<EuiText size="s">{content}</EuiText>
<EuiSpacer />
<FormattedMessage
id="xpack.apm.serviceGroups.tour.content.link"
defaultMessage="Learn more in the {docsLink}."
values={{
docsLink: (
<ElasticDocsLink
section="/kibana"
path="/services.html"
target="blank"
>
{i18n.translate(
'xpack.apm.serviceGroups.tour.content.link.docs',
{
defaultMessage: 'docs',
}
)}
</ElasticDocsLink>
),
}}
/>
</>
}
isStepOpen={tourEnabled}
onFinish={() => {}}
maxWidth={300}
minWidth={300}
step={1}
stepsTotal={1}
title={title}
anchorPosition="leftUp"
footerAction={
<EuiButtonEmpty color="text" size="xs" onClick={dismissTour}>
{i18n.translate('xpack.apm.serviceGroups.tour.dismiss', {
defaultMessage: 'Dismiss',
})}
</EuiButtonEmpty>
}
>
{children}
</EuiTourStep>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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 { useLocalStorage } from '../../../hooks/use_local_storage';
import { TourType } from './service_groups_tour';

const INITIAL_STATE: Record<TourType, boolean> = {
createGroup: true,
editGroup: true,
serviceGroupCard: true,
};

export function useServiceGroupsTour(type: TourType) {
const [tourEnabled, setTourEnabled] = useLocalStorage(
'apm.serviceGroupsTour',
INITIAL_STATE
);

return {
tourEnabled: tourEnabled[type],
dismissTour: () =>
setTourEnabled({
...tourEnabled,
[type]: false,
}),
};
}

0 comments on commit cf082dd

Please sign in to comment.