Skip to content

Commit c5cbc5f

Browse files
authored
[EDR Workflows] Unify artifacts empty state buttons (elastic#264389)
## Summary As now we're adding a new secondary button for artifact _Import_ to the empty state pages of Artifact page and Policy details page, this PR aims to unify the UI a bit. - [x] 'Add artifact' button and 'Import artifacts' empty button are now vertically aligned on **Artifacts** page's empty state <img width="600" alt="artifacts" src="https://github.com/user-attachments/assets/ccd94868-8521-4ffa-81f8-d2fb8016d4cb" /> - [x] Same vertical alignment on **Policy details** page's artifact tabs <img width="600" alt="policy details" src="https://github.com/user-attachments/assets/e605b047-d889-46e6-82bf-b336d7273cda" /> - [x] When arriving to **Artifacts** page from **Policy details** page, the (now) 3rd button is changed to a simple link <img width="600" alt="bakc" src="https://github.com/user-attachments/assets/a6fe0f98-5088-4e76-a111-485261c87da1" /> - [x] On **Policy details** page's 'artifacts exist, but they are not assigned' empty state the old 'Manage artifacts' link is changed to an empty button to harmonize with the new Import button <img width="600" alt="manage" src="https://github.com/user-attachments/assets/8d20e532-ca97-41dd-b201-57624457df91" /> ## Testing To see the Import button, enable the following feature flag: ``` xpack.securitySolution.enableExperimental: - endpointExceptionsMovedUnderManagement ```
1 parent fc676fa commit c5cbc5f

6 files changed

Lines changed: 66 additions & 60 deletions

File tree

x-pack/solutions/security/plugins/security_solution/public/management/components/artifact_list_page/artifact_list_page.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ import { DEFAULT_EXCEPTION_LIST_ITEM_SEARCHABLE_FIELDS } from '../../../../commo
5858
import { ArtifactDeleteModal } from './components/artifact_delete_modal';
5959
import { useKibana, useToasts } from '../../../common/lib/kibana';
6060
import { useMemoizedRouteState } from '../../common/hooks';
61-
import { BackToExternalAppSecondaryButton } from '../back_to_external_app_secondary_button';
61+
import { BackToExternalAppLink } from '../back_to_external_app_link';
6262
import { BackToExternalAppButton } from '../back_to_external_app_button';
6363
import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features';
6464
import { ArtifactImportFlyout } from './components/artifact_import_flyout';
@@ -204,9 +204,9 @@ export const ArtifactListPage = memo<ArtifactListPageProps>(
204204

205205
const memoizedRouteState = useMemoizedRouteState(routeState);
206206

207-
const backButtonEmptyComponent = useMemo(() => {
207+
const backLinkComponent = useMemo(() => {
208208
if (memoizedRouteState && memoizedRouteState.onBackButtonNavigateTo) {
209-
return <BackToExternalAppSecondaryButton {...memoizedRouteState} />;
209+
return <BackToExternalAppLink {...memoizedRouteState} />;
210210
}
211211
}, [memoizedRouteState]);
212212

@@ -443,7 +443,7 @@ export const ArtifactListPage = memo<ArtifactListPageProps>(
443443
aboutInfo={labels.emptyStateInfo}
444444
primaryButtonLabel={labels.emptyStatePrimaryButtonLabel}
445445
importButtonLabel={labels.emptyStateImportButtonLabel}
446-
backComponent={backButtonEmptyComponent}
446+
backComponent={backLinkComponent}
447447
data-test-subj={getTestId('emptyState')}
448448
secondaryAboutInfo={secondaryPageInfo}
449449
canCreateItems={allowCardCreateAction}

x-pack/solutions/security/plugins/security_solution/public/management/components/artifact_list_page/components/no_data_empty_state.tsx

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import React, { memo } from 'react';
99
import styled, { css } from 'styled-components';
10-
import { EuiButton, EuiEmptyPrompt, EuiFlexGroup, EuiSpacer } from '@elastic/eui';
10+
import { EuiButton, EuiButtonEmpty, EuiEmptyPrompt, EuiSpacer } from '@elastic/eui';
1111
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features';
1212
import { ManagementEmptyStateWrapper } from '../../management_empty_state_wrapper';
1313
import { useTestIdGenerator } from '../../../hooks/use_test_id_generator';
@@ -71,25 +71,27 @@ export const NoDataEmptyState = memo<{
7171
</div>
7272
}
7373
actions={[
74-
<EuiFlexGroup>
75-
<EuiButton
76-
fill
77-
isDisabled={isAddDisabled}
78-
onClick={onAdd}
79-
data-test-subj={getTestId('addButton')}
80-
>
81-
{primaryButtonLabel}
82-
</EuiButton>
83-
{isEndpointExceptionsMovedUnderManagementFFEnabled && (
84-
<EuiButton
85-
isDisabled={isAddDisabled}
86-
onClick={onImport}
87-
data-test-subj={getTestId('importButton')}
88-
>
89-
{importButtonLabel}
90-
</EuiButton>
91-
)}
92-
</EuiFlexGroup>,
74+
<EuiButton
75+
fill
76+
isDisabled={isAddDisabled}
77+
onClick={onAdd}
78+
data-test-subj={getTestId('addButton')}
79+
>
80+
{primaryButtonLabel}
81+
</EuiButton>,
82+
83+
...(isEndpointExceptionsMovedUnderManagementFFEnabled
84+
? [
85+
<EuiButtonEmpty
86+
isDisabled={isAddDisabled}
87+
onClick={onImport}
88+
data-test-subj={getTestId('importButton')}
89+
>
90+
{importButtonLabel}
91+
</EuiButtonEmpty>,
92+
]
93+
: []),
94+
9395
...(backComponent ? [backComponent] : []),
9496
]}
9597
/>

x-pack/solutions/security/plugins/security_solution/public/management/components/back_to_external_app_secondary_button/back_to_external_app_secondary_button.tsx renamed to x-pack/solutions/security/plugins/security_solution/public/management/components/back_to_external_app_link/back_to_external_app_link.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,34 @@ import React, { memo } from 'react';
88

99
import { FormattedMessage } from '@kbn/i18n-react';
1010
import type { CommonProps } from '@elastic/eui';
11-
import { EuiButtonEmpty } from '@elastic/eui';
11+
import { EuiFlexGroup, EuiIcon, EuiLink } from '@elastic/eui';
1212

1313
import type { ListPageRouteState } from '../../../../common/endpoint/types';
1414

1515
import { useNavigateToAppEventHandler } from '../../../common/hooks/endpoint/use_navigate_to_app_event_handler';
1616

17-
export type BackToExternalAppSecondaryButtonProps = CommonProps & ListPageRouteState;
18-
export const BackToExternalAppSecondaryButton = memo<BackToExternalAppSecondaryButtonProps>(
17+
export type BackToExternalAppLinkProps = CommonProps & ListPageRouteState;
18+
export const BackToExternalAppLink = memo<BackToExternalAppLinkProps>(
1919
({ backButtonLabel, backButtonUrl, onBackButtonNavigateTo, ...commonProps }) => {
2020
const handleBackOnClick = useNavigateToAppEventHandler(...onBackButtonNavigateTo);
2121

2222
return (
2323
// eslint-disable-next-line @elastic/eui/href-or-on-click
24-
<EuiButtonEmpty
24+
<EuiLink
2525
{...commonProps}
2626
data-test-subj="backToOrigin"
27-
size="s"
2827
href={backButtonUrl}
2928
onClick={handleBackOnClick}
30-
textProps={{ className: 'text' }}
3129
>
32-
{backButtonLabel || (
33-
<FormattedMessage id="xpack.securitySolution.list.backButton" defaultMessage="Back" />
34-
)}
35-
</EuiButtonEmpty>
30+
<EuiFlexGroup alignItems="center" gutterSize="xs" responsive={false}>
31+
<EuiIcon type="arrowLeft" size="s" aria-hidden={true} />
32+
{backButtonLabel || (
33+
<FormattedMessage id="xpack.securitySolution.list.backButton" defaultMessage="Back" />
34+
)}
35+
</EuiFlexGroup>
36+
</EuiLink>
3637
);
3738
}
3839
);
3940

40-
BackToExternalAppSecondaryButton.displayName = 'BackToExternalAppSecondaryButton';
41+
BackToExternalAppLink.displayName = 'BackToExternalAppLink';

x-pack/solutions/security/plugins/security_solution/public/management/components/back_to_external_app_secondary_button/index.ts renamed to x-pack/solutions/security/plugins/security_solution/public/management/components/back_to_external_app_link/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
* 2.0.
66
*/
77

8-
export { BackToExternalAppSecondaryButton } from './back_to_external_app_secondary_button';
8+
export { BackToExternalAppLink } from './back_to_external_app_link';

x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/artifacts/empty/policy_artifacts_empty_unassigned.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77

88
import React, { memo, useCallback } from 'react';
9-
import { EuiButton, EuiLink, EuiPageTemplate } from '@elastic/eui';
9+
import { EuiButton, EuiButtonEmpty, EuiPageTemplate } from '@elastic/eui';
1010
import { usePolicyDetailsArtifactsNavigateCallback } from '../../policy_hooks';
1111
import { useGetLinkTo } from './use_policy_artifacts_empty_hooks';
1212
import { useUserPrivileges } from '../../../../../../common/components/user_privileges';
@@ -74,13 +74,14 @@ export const PolicyArtifactsEmptyUnassigned = memo<CommonProps>(
7474
: []),
7575
canWriteArtifact ? (
7676
// eslint-disable-next-line @elastic/eui/href-or-on-click
77-
<EuiLink
77+
<EuiButtonEmpty
7878
onClick={onClickHandler}
7979
href={toRouteUrl}
80+
size="m"
8081
data-test-subj="unassigned-manage-artifacts-button"
8182
>
8283
{labels.emptyUnassignedSecondaryActionButtonTitle}
83-
</EuiLink>
84+
</EuiButtonEmpty>
8485
) : null,
8586
]}
8687
/>

x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/artifacts/empty/policy_artifacts_empty_unexisting.tsx

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77

88
import React, { memo } from 'react';
9-
import { EuiButton, EuiFlexGroup, EuiPageTemplate } from '@elastic/eui';
9+
import { EuiButton, EuiButtonEmpty, EuiPageTemplate } from '@elastic/eui';
1010
import { useIsExperimentalFeatureEnabled } from '../../../../../../common/hooks/use_experimental_features';
1111
import { useGetLinkTo } from './use_policy_artifacts_empty_hooks';
1212
import type { POLICY_ARTIFACT_EMPTY_UNEXISTING_LABELS } from './translations';
@@ -61,33 +61,35 @@ export const PolicyArtifactsEmptyUnexisting = memo<CommonProps>(
6161
data-test-subj="policy-artifacts-empty-unexisting"
6262
title={<h2>{labels.emptyUnexistingTitle}</h2>}
6363
body={labels.emptyUnexistingMessage}
64-
actions={
65-
canWriteArtifact ? (
66-
<EuiFlexGroup justifyContent="center">
67-
{/* eslint-disable-next-line @elastic/eui/href-or-on-click */}
68-
<EuiButton
69-
color="primary"
70-
fill
71-
onClick={onAddClickHandler}
72-
href={toAddRouteUrl}
73-
data-test-subj="unexisting-manage-artifacts-button"
74-
>
75-
{labels.emptyUnexistingPrimaryActionButtonTitle}
76-
</EuiButton>
64+
actions={[
65+
...(canWriteArtifact
66+
? [
67+
/* eslint-disable-next-line @elastic/eui/href-or-on-click */
68+
<EuiButton
69+
color="primary"
70+
fill
71+
onClick={onAddClickHandler}
72+
href={toAddRouteUrl}
73+
data-test-subj="unexisting-manage-artifacts-button"
74+
>
75+
{labels.emptyUnexistingPrimaryActionButtonTitle}
76+
</EuiButton>,
77+
]
78+
: []),
7779

78-
{isEndpointExceptionsMovedUnderManagementFFEnabled && (
80+
...(canWriteArtifact && isEndpointExceptionsMovedUnderManagementFFEnabled
81+
? [
7982
// eslint-disable-next-line @elastic/eui/href-or-on-click
80-
<EuiButton
83+
<EuiButtonEmpty
8184
onClick={onImportClickHandler}
8285
href={toImportRouteUrl}
8386
data-test-subj="unexisting-manage-artifacts-import-button"
8487
>
8588
{labels.emptyUnexistingImportButtonTitle}
86-
</EuiButton>
87-
)}
88-
</EuiFlexGroup>
89-
) : null
90-
}
89+
</EuiButtonEmpty>,
90+
]
91+
: []),
92+
]}
9193
/>
9294
);
9395
}

0 commit comments

Comments
 (0)