mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[ENDPOINT] Reintroduced tabs to endpoint management and migrated pages to use common security components (#74886) (#75352)
* Reintroduced tabs to endpoint management and migrated pages to use common security components. * Empty trusted apps tab. * Changed casing in the translations. * Switched to using route path generation functions. * Added propagation of data-test-subj attribute to Wrapper component. * Fixed CommonProps import. * Moved out shared component for administration list page. * Removed unused file. * Removed unused translation keys. * Removed redundant snapshot. * Added some minimal tests. * Attempt to fix functional tests. * Attempt to fix functional tests again. * Reverted function declarations back to const. * Wrapped component in memo.
This commit is contained in:
parent
27f124a8c0
commit
c1b50e6a05
31 changed files with 325 additions and 1274 deletions
|
@ -1,802 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`PageView component should display body header custom element 1`] = `
|
||||
.c0.endpoint--isListView {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-header {
|
||||
padding: 24px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-page-content {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.c0.endpoint--isDetailsView .endpoint-page-content {
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.c0 .endpoint-navTabs {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.c0 .endpoint-header-leftSection {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
<PageView
|
||||
bodyHeader={
|
||||
<p>
|
||||
body header
|
||||
</p>
|
||||
}
|
||||
viewType="list"
|
||||
>
|
||||
<Styled(EuiPage)
|
||||
className="endpoint--isListView"
|
||||
>
|
||||
<EuiPage
|
||||
className="c0 endpoint--isListView"
|
||||
>
|
||||
<div
|
||||
className="euiPage c0 endpoint--isListView"
|
||||
>
|
||||
<EuiPageBody>
|
||||
<main
|
||||
className="euiPageBody"
|
||||
>
|
||||
<EuiPageContent
|
||||
className="endpoint-page-content"
|
||||
>
|
||||
<EuiPanel
|
||||
className="euiPageContent endpoint-page-content"
|
||||
paddingSize="l"
|
||||
>
|
||||
<div
|
||||
className="euiPanel euiPanel--paddingLarge euiPageContent endpoint-page-content"
|
||||
>
|
||||
<EuiPageContentHeader>
|
||||
<div
|
||||
className="euiPageContentHeader euiPageContentHeader--responsive"
|
||||
>
|
||||
<EuiPageContentHeaderSection
|
||||
data-test-subj="pageViewBodyTitleArea"
|
||||
>
|
||||
<div
|
||||
className="euiPageContentHeaderSection"
|
||||
data-test-subj="pageViewBodyTitleArea"
|
||||
>
|
||||
<p>
|
||||
body header
|
||||
</p>
|
||||
</div>
|
||||
</EuiPageContentHeaderSection>
|
||||
</div>
|
||||
</EuiPageContentHeader>
|
||||
<EuiPageContentBody
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
<div
|
||||
className="euiPageContentBody"
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
body content
|
||||
</div>
|
||||
</EuiPageContentBody>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
</EuiPageContent>
|
||||
</main>
|
||||
</EuiPageBody>
|
||||
</div>
|
||||
</EuiPage>
|
||||
</Styled(EuiPage)>
|
||||
</PageView>
|
||||
`;
|
||||
|
||||
exports[`PageView component should display body header wrapped in EuiTitle 1`] = `
|
||||
.c0.endpoint--isListView {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-header {
|
||||
padding: 24px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-page-content {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.c0.endpoint--isDetailsView .endpoint-page-content {
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.c0 .endpoint-navTabs {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.c0 .endpoint-header-leftSection {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
<PageView
|
||||
bodyHeader="body header"
|
||||
viewType="list"
|
||||
>
|
||||
<Styled(EuiPage)
|
||||
className="endpoint--isListView"
|
||||
>
|
||||
<EuiPage
|
||||
className="c0 endpoint--isListView"
|
||||
>
|
||||
<div
|
||||
className="euiPage c0 endpoint--isListView"
|
||||
>
|
||||
<EuiPageBody>
|
||||
<main
|
||||
className="euiPageBody"
|
||||
>
|
||||
<EuiPageContent
|
||||
className="endpoint-page-content"
|
||||
>
|
||||
<EuiPanel
|
||||
className="euiPageContent endpoint-page-content"
|
||||
paddingSize="l"
|
||||
>
|
||||
<div
|
||||
className="euiPanel euiPanel--paddingLarge euiPageContent endpoint-page-content"
|
||||
>
|
||||
<EuiPageContentHeader>
|
||||
<div
|
||||
className="euiPageContentHeader euiPageContentHeader--responsive"
|
||||
>
|
||||
<EuiPageContentHeaderSection
|
||||
data-test-subj="pageViewBodyTitleArea"
|
||||
>
|
||||
<div
|
||||
className="euiPageContentHeaderSection"
|
||||
data-test-subj="pageViewBodyTitleArea"
|
||||
>
|
||||
<PageViewBodyHeaderTitle>
|
||||
<EuiTitle>
|
||||
<h2
|
||||
className="euiTitle euiTitle--medium"
|
||||
data-test-subj="pageViewBodyTitle"
|
||||
>
|
||||
body header
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
</PageViewBodyHeaderTitle>
|
||||
</div>
|
||||
</EuiPageContentHeaderSection>
|
||||
</div>
|
||||
</EuiPageContentHeader>
|
||||
<EuiPageContentBody
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
<div
|
||||
className="euiPageContentBody"
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
body content
|
||||
</div>
|
||||
</EuiPageContentBody>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
</EuiPageContent>
|
||||
</main>
|
||||
</EuiPageBody>
|
||||
</div>
|
||||
</EuiPage>
|
||||
</Styled(EuiPage)>
|
||||
</PageView>
|
||||
`;
|
||||
|
||||
exports[`PageView component should display header left and right 1`] = `
|
||||
.c0.endpoint--isListView {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-header {
|
||||
padding: 24px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-page-content {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.c0.endpoint--isDetailsView .endpoint-page-content {
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.c0 .endpoint-navTabs {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.c0 .endpoint-header-leftSection {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
<PageView
|
||||
headerLeft="page title"
|
||||
headerRight="right side actions"
|
||||
viewType="list"
|
||||
>
|
||||
<Styled(EuiPage)
|
||||
className="endpoint--isListView"
|
||||
>
|
||||
<EuiPage
|
||||
className="c0 endpoint--isListView"
|
||||
>
|
||||
<div
|
||||
className="euiPage c0 endpoint--isListView"
|
||||
>
|
||||
<EuiPageBody>
|
||||
<main
|
||||
className="euiPageBody"
|
||||
>
|
||||
<EuiPageHeader
|
||||
className="endpoint-header"
|
||||
>
|
||||
<div
|
||||
className="euiPageHeader euiPageHeader--responsive endpoint-header"
|
||||
>
|
||||
<EuiPageHeaderSection
|
||||
className="endpoint-header-leftSection"
|
||||
data-test-subj="pageViewHeaderLeft"
|
||||
>
|
||||
<div
|
||||
className="euiPageHeaderSection endpoint-header-leftSection"
|
||||
data-test-subj="pageViewHeaderLeft"
|
||||
>
|
||||
<PageViewHeaderTitle>
|
||||
<EuiTitle
|
||||
size="l"
|
||||
>
|
||||
<h1
|
||||
className="euiTitle euiTitle--large"
|
||||
data-test-subj="pageViewHeaderLeftTitle"
|
||||
>
|
||||
page title
|
||||
</h1>
|
||||
</EuiTitle>
|
||||
</PageViewHeaderTitle>
|
||||
</div>
|
||||
</EuiPageHeaderSection>
|
||||
<EuiPageHeaderSection
|
||||
data-test-subj="pageViewHeaderRight"
|
||||
>
|
||||
<div
|
||||
className="euiPageHeaderSection"
|
||||
data-test-subj="pageViewHeaderRight"
|
||||
>
|
||||
right side actions
|
||||
</div>
|
||||
</EuiPageHeaderSection>
|
||||
</div>
|
||||
</EuiPageHeader>
|
||||
<EuiPageContent
|
||||
className="endpoint-page-content"
|
||||
>
|
||||
<EuiPanel
|
||||
className="euiPageContent endpoint-page-content"
|
||||
paddingSize="l"
|
||||
>
|
||||
<div
|
||||
className="euiPanel euiPanel--paddingLarge euiPageContent endpoint-page-content"
|
||||
>
|
||||
<EuiPageContentBody
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
<div
|
||||
className="euiPageContentBody"
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
body content
|
||||
</div>
|
||||
</EuiPageContentBody>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
</EuiPageContent>
|
||||
</main>
|
||||
</EuiPageBody>
|
||||
</div>
|
||||
</EuiPage>
|
||||
</Styled(EuiPage)>
|
||||
</PageView>
|
||||
`;
|
||||
|
||||
exports[`PageView component should display only body if not header props used 1`] = `
|
||||
.c0.endpoint--isListView {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-header {
|
||||
padding: 24px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-page-content {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.c0.endpoint--isDetailsView .endpoint-page-content {
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.c0 .endpoint-navTabs {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.c0 .endpoint-header-leftSection {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
<PageView
|
||||
viewType="list"
|
||||
>
|
||||
<Styled(EuiPage)
|
||||
className="endpoint--isListView"
|
||||
>
|
||||
<EuiPage
|
||||
className="c0 endpoint--isListView"
|
||||
>
|
||||
<div
|
||||
className="euiPage c0 endpoint--isListView"
|
||||
>
|
||||
<EuiPageBody>
|
||||
<main
|
||||
className="euiPageBody"
|
||||
>
|
||||
<EuiPageContent
|
||||
className="endpoint-page-content"
|
||||
>
|
||||
<EuiPanel
|
||||
className="euiPageContent endpoint-page-content"
|
||||
paddingSize="l"
|
||||
>
|
||||
<div
|
||||
className="euiPanel euiPanel--paddingLarge euiPageContent endpoint-page-content"
|
||||
>
|
||||
<EuiPageContentBody
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
<div
|
||||
className="euiPageContentBody"
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
body content
|
||||
</div>
|
||||
</EuiPageContentBody>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
</EuiPageContent>
|
||||
</main>
|
||||
</EuiPageBody>
|
||||
</div>
|
||||
</EuiPage>
|
||||
</Styled(EuiPage)>
|
||||
</PageView>
|
||||
`;
|
||||
|
||||
exports[`PageView component should display only header left 1`] = `
|
||||
.c0.endpoint--isListView {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-header {
|
||||
padding: 24px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-page-content {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.c0.endpoint--isDetailsView .endpoint-page-content {
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.c0 .endpoint-navTabs {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.c0 .endpoint-header-leftSection {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
<PageView
|
||||
headerLeft="page title"
|
||||
viewType="list"
|
||||
>
|
||||
<Styled(EuiPage)
|
||||
className="endpoint--isListView"
|
||||
>
|
||||
<EuiPage
|
||||
className="c0 endpoint--isListView"
|
||||
>
|
||||
<div
|
||||
className="euiPage c0 endpoint--isListView"
|
||||
>
|
||||
<EuiPageBody>
|
||||
<main
|
||||
className="euiPageBody"
|
||||
>
|
||||
<EuiPageHeader
|
||||
className="endpoint-header"
|
||||
>
|
||||
<div
|
||||
className="euiPageHeader euiPageHeader--responsive endpoint-header"
|
||||
>
|
||||
<EuiPageHeaderSection
|
||||
className="endpoint-header-leftSection"
|
||||
data-test-subj="pageViewHeaderLeft"
|
||||
>
|
||||
<div
|
||||
className="euiPageHeaderSection endpoint-header-leftSection"
|
||||
data-test-subj="pageViewHeaderLeft"
|
||||
>
|
||||
<PageViewHeaderTitle>
|
||||
<EuiTitle
|
||||
size="l"
|
||||
>
|
||||
<h1
|
||||
className="euiTitle euiTitle--large"
|
||||
data-test-subj="pageViewHeaderLeftTitle"
|
||||
>
|
||||
page title
|
||||
</h1>
|
||||
</EuiTitle>
|
||||
</PageViewHeaderTitle>
|
||||
</div>
|
||||
</EuiPageHeaderSection>
|
||||
</div>
|
||||
</EuiPageHeader>
|
||||
<EuiPageContent
|
||||
className="endpoint-page-content"
|
||||
>
|
||||
<EuiPanel
|
||||
className="euiPageContent endpoint-page-content"
|
||||
paddingSize="l"
|
||||
>
|
||||
<div
|
||||
className="euiPanel euiPanel--paddingLarge euiPageContent endpoint-page-content"
|
||||
>
|
||||
<EuiPageContentBody
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
<div
|
||||
className="euiPageContentBody"
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
body content
|
||||
</div>
|
||||
</EuiPageContentBody>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
</EuiPageContent>
|
||||
</main>
|
||||
</EuiPageBody>
|
||||
</div>
|
||||
</EuiPage>
|
||||
</Styled(EuiPage)>
|
||||
</PageView>
|
||||
`;
|
||||
|
||||
exports[`PageView component should display only header right but include an empty left side 1`] = `
|
||||
.c0.endpoint--isListView {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-header {
|
||||
padding: 24px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-page-content {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.c0.endpoint--isDetailsView .endpoint-page-content {
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.c0 .endpoint-navTabs {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.c0 .endpoint-header-leftSection {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
<PageView
|
||||
headerRight="right side actions"
|
||||
viewType="list"
|
||||
>
|
||||
<Styled(EuiPage)
|
||||
className="endpoint--isListView"
|
||||
>
|
||||
<EuiPage
|
||||
className="c0 endpoint--isListView"
|
||||
>
|
||||
<div
|
||||
className="euiPage c0 endpoint--isListView"
|
||||
>
|
||||
<EuiPageBody>
|
||||
<main
|
||||
className="euiPageBody"
|
||||
>
|
||||
<EuiPageHeader
|
||||
className="endpoint-header"
|
||||
>
|
||||
<div
|
||||
className="euiPageHeader euiPageHeader--responsive endpoint-header"
|
||||
>
|
||||
<EuiPageHeaderSection
|
||||
className="endpoint-header-leftSection"
|
||||
data-test-subj="pageViewHeaderLeft"
|
||||
>
|
||||
<div
|
||||
className="euiPageHeaderSection endpoint-header-leftSection"
|
||||
data-test-subj="pageViewHeaderLeft"
|
||||
/>
|
||||
</EuiPageHeaderSection>
|
||||
<EuiPageHeaderSection
|
||||
data-test-subj="pageViewHeaderRight"
|
||||
>
|
||||
<div
|
||||
className="euiPageHeaderSection"
|
||||
data-test-subj="pageViewHeaderRight"
|
||||
>
|
||||
right side actions
|
||||
</div>
|
||||
</EuiPageHeaderSection>
|
||||
</div>
|
||||
</EuiPageHeader>
|
||||
<EuiPageContent
|
||||
className="endpoint-page-content"
|
||||
>
|
||||
<EuiPanel
|
||||
className="euiPageContent endpoint-page-content"
|
||||
paddingSize="l"
|
||||
>
|
||||
<div
|
||||
className="euiPanel euiPanel--paddingLarge euiPageContent endpoint-page-content"
|
||||
>
|
||||
<EuiPageContentBody
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
<div
|
||||
className="euiPageContentBody"
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
body content
|
||||
</div>
|
||||
</EuiPageContentBody>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
</EuiPageContent>
|
||||
</main>
|
||||
</EuiPageBody>
|
||||
</div>
|
||||
</EuiPage>
|
||||
</Styled(EuiPage)>
|
||||
</PageView>
|
||||
`;
|
||||
|
||||
exports[`PageView component should pass through EuiPage props 1`] = `
|
||||
.c0.endpoint--isListView {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-header {
|
||||
padding: 24px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-page-content {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.c0.endpoint--isDetailsView .endpoint-page-content {
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.c0 .endpoint-navTabs {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.c0 .endpoint-header-leftSection {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
<PageView
|
||||
aria-label="test-aria-label-here"
|
||||
className="test-class-name-here"
|
||||
data-test-subj="test-data-test-subj-here"
|
||||
restrictWidth="1000"
|
||||
viewType="list"
|
||||
>
|
||||
<Styled(EuiPage)
|
||||
aria-label="test-aria-label-here"
|
||||
className="test-class-name-here"
|
||||
data-test-subj="test-data-test-subj-here"
|
||||
restrictWidth="1000"
|
||||
>
|
||||
<EuiPage
|
||||
aria-label="test-aria-label-here"
|
||||
className="c0 test-class-name-here"
|
||||
data-test-subj="test-data-test-subj-here"
|
||||
restrictWidth="1000"
|
||||
>
|
||||
<div
|
||||
aria-label="test-aria-label-here"
|
||||
className="euiPage euiPage--restrictWidth-custom c0 test-class-name-here"
|
||||
data-test-subj="test-data-test-subj-here"
|
||||
style={
|
||||
Object {
|
||||
"maxWidth": "1000",
|
||||
}
|
||||
}
|
||||
>
|
||||
<EuiPageBody>
|
||||
<main
|
||||
className="euiPageBody"
|
||||
>
|
||||
<EuiPageContent
|
||||
className="endpoint-page-content"
|
||||
>
|
||||
<EuiPanel
|
||||
className="euiPageContent endpoint-page-content"
|
||||
paddingSize="l"
|
||||
>
|
||||
<div
|
||||
className="euiPanel euiPanel--paddingLarge euiPageContent endpoint-page-content"
|
||||
>
|
||||
<EuiPageContentBody
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
<div
|
||||
className="euiPageContentBody"
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
body content
|
||||
</div>
|
||||
</EuiPageContentBody>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
</EuiPageContent>
|
||||
</main>
|
||||
</EuiPageBody>
|
||||
</div>
|
||||
</EuiPage>
|
||||
</Styled(EuiPage)>
|
||||
</PageView>
|
||||
`;
|
||||
|
||||
exports[`PageView component should use custom element for header left and not wrap in EuiTitle 1`] = `
|
||||
.c0.endpoint--isListView {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-header {
|
||||
padding: 24px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.c0.endpoint--isListView .endpoint-page-content {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.c0.endpoint--isDetailsView .endpoint-page-content {
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.c0 .endpoint-navTabs {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.c0 .endpoint-header-leftSection {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
<PageView
|
||||
headerLeft={
|
||||
<p>
|
||||
title here
|
||||
</p>
|
||||
}
|
||||
viewType="list"
|
||||
>
|
||||
<Styled(EuiPage)
|
||||
className="endpoint--isListView"
|
||||
>
|
||||
<EuiPage
|
||||
className="c0 endpoint--isListView"
|
||||
>
|
||||
<div
|
||||
className="euiPage c0 endpoint--isListView"
|
||||
>
|
||||
<EuiPageBody>
|
||||
<main
|
||||
className="euiPageBody"
|
||||
>
|
||||
<EuiPageHeader
|
||||
className="endpoint-header"
|
||||
>
|
||||
<div
|
||||
className="euiPageHeader euiPageHeader--responsive endpoint-header"
|
||||
>
|
||||
<EuiPageHeaderSection
|
||||
className="endpoint-header-leftSection"
|
||||
data-test-subj="pageViewHeaderLeft"
|
||||
>
|
||||
<div
|
||||
className="euiPageHeaderSection endpoint-header-leftSection"
|
||||
data-test-subj="pageViewHeaderLeft"
|
||||
>
|
||||
<p>
|
||||
title here
|
||||
</p>
|
||||
</div>
|
||||
</EuiPageHeaderSection>
|
||||
</div>
|
||||
</EuiPageHeader>
|
||||
<EuiPageContent
|
||||
className="endpoint-page-content"
|
||||
>
|
||||
<EuiPanel
|
||||
className="euiPageContent endpoint-page-content"
|
||||
paddingSize="l"
|
||||
>
|
||||
<div
|
||||
className="euiPanel euiPanel--paddingLarge euiPageContent endpoint-page-content"
|
||||
>
|
||||
<EuiPageContentBody
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
<div
|
||||
className="euiPageContentBody"
|
||||
data-test-subj="pageViewBodyContent"
|
||||
>
|
||||
body content
|
||||
</div>
|
||||
</EuiPageContentBody>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
</EuiPageContent>
|
||||
</main>
|
||||
</EuiPageBody>
|
||||
</div>
|
||||
</EuiPage>
|
||||
</Styled(EuiPage)>
|
||||
</PageView>
|
||||
`;
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { PageView } from './page_view';
|
||||
import { EuiThemeProvider } from '../../../../../../legacy/common/eui_styled_components';
|
||||
|
||||
describe('PageView component', () => {
|
||||
const render = (ui: Parameters<typeof mount>[0]) =>
|
||||
mount(ui, { wrappingComponent: EuiThemeProvider });
|
||||
|
||||
it('should display only body if not header props used', () => {
|
||||
expect(render(<PageView viewType="list">{'body content'}</PageView>)).toMatchSnapshot();
|
||||
});
|
||||
it('should display header left and right', () => {
|
||||
expect(
|
||||
render(
|
||||
<PageView viewType="list" headerLeft="page title" headerRight="right side actions">
|
||||
{'body content'}
|
||||
</PageView>
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
it('should display only header left', () => {
|
||||
expect(
|
||||
render(
|
||||
<PageView viewType="list" headerLeft="page title">
|
||||
{'body content'}
|
||||
</PageView>
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
it('should display only header right but include an empty left side', () => {
|
||||
expect(
|
||||
render(
|
||||
<PageView viewType="list" headerRight="right side actions">
|
||||
{'body content'}
|
||||
</PageView>
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
it(`should use custom element for header left and not wrap in EuiTitle`, () => {
|
||||
expect(
|
||||
render(
|
||||
<PageView viewType="list" headerLeft={<p>{'title here'}</p>}>
|
||||
{'body content'}
|
||||
</PageView>
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
it('should display body header wrapped in EuiTitle', () => {
|
||||
expect(
|
||||
render(
|
||||
<PageView viewType="list" bodyHeader="body header">
|
||||
{'body content'}
|
||||
</PageView>
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
it('should display body header custom element', () => {
|
||||
expect(
|
||||
render(
|
||||
<PageView viewType="list" bodyHeader={<p>{'body header'}</p>}>
|
||||
{'body content'}
|
||||
</PageView>
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
it('should pass through EuiPage props', () => {
|
||||
expect(
|
||||
render(
|
||||
<PageView
|
||||
viewType="list"
|
||||
restrictWidth="1000"
|
||||
className="test-class-name-here"
|
||||
aria-label="test-aria-label-here"
|
||||
data-test-subj="test-data-test-subj-here"
|
||||
>
|
||||
{'body content'}
|
||||
</PageView>
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import {
|
||||
EuiPage,
|
||||
EuiPageBody,
|
||||
EuiPageContent,
|
||||
EuiPageContentBody,
|
||||
EuiPageContentHeader,
|
||||
EuiPageContentHeaderSection,
|
||||
EuiPageHeader,
|
||||
EuiPageHeaderSection,
|
||||
EuiPageProps,
|
||||
EuiTab,
|
||||
EuiTabs,
|
||||
EuiTitle,
|
||||
EuiTitleProps,
|
||||
} from '@elastic/eui';
|
||||
import React, { memo, MouseEventHandler, ReactNode, useMemo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { EuiTabProps } from '@elastic/eui/src/components/tabs/tab';
|
||||
|
||||
const StyledEuiPage = styled(EuiPage)`
|
||||
&.endpoint--isListView {
|
||||
padding: 0 ${(props) => props.theme.eui.euiSizeL};
|
||||
|
||||
.endpoint-header {
|
||||
padding: ${(props) => props.theme.eui.euiSizeL};
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.endpoint-page-content {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
&.endpoint--isDetailsView {
|
||||
.endpoint-page-content {
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
.endpoint-navTabs {
|
||||
margin-left: ${(props) => props.theme.eui.euiSizeM};
|
||||
}
|
||||
.endpoint-header-leftSection {
|
||||
overflow: hidden;
|
||||
}
|
||||
`;
|
||||
|
||||
const isStringOrNumber = /(string|number)/;
|
||||
|
||||
/**
|
||||
* The `PageView` component used to render `headerLeft` when it is set as a `string`
|
||||
* Can be used when wanting to customize the `headerLeft` value but still use the standard
|
||||
* title component
|
||||
*/
|
||||
export const PageViewHeaderTitle = memo<Omit<EuiTitleProps, 'children'> & { children: ReactNode }>(
|
||||
({ children, size = 'l', ...otherProps }) => {
|
||||
return (
|
||||
<EuiTitle {...otherProps} size={size}>
|
||||
<h1 data-test-subj="pageViewHeaderLeftTitle">{children}</h1>
|
||||
</EuiTitle>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
PageViewHeaderTitle.displayName = 'PageViewHeaderTitle';
|
||||
|
||||
/**
|
||||
* The `PageView` component used to render `bodyHeader` when it is set as a `string`
|
||||
* Can be used when wanting to customize the `bodyHeader` value but still use the standard
|
||||
* title component
|
||||
*/
|
||||
export const PageViewBodyHeaderTitle = memo<{ children: ReactNode }>(
|
||||
({ children, ...otherProps }) => {
|
||||
return (
|
||||
<EuiTitle {...otherProps}>
|
||||
<h2 data-test-subj="pageViewBodyTitle">{children}</h2>
|
||||
</EuiTitle>
|
||||
);
|
||||
}
|
||||
);
|
||||
PageViewBodyHeaderTitle.displayName = 'PageViewBodyHeaderTitle';
|
||||
|
||||
export type PageViewProps = EuiPageProps & {
|
||||
/**
|
||||
* The type of view
|
||||
*/
|
||||
viewType: 'list' | 'details';
|
||||
/**
|
||||
* content to be placed on the left side of the header. If a `string` is used, then it will
|
||||
* be wrapped with `<EuiTitle><h1></h1></EuiTitle>`, else it will just be used as is.
|
||||
*/
|
||||
headerLeft?: ReactNode;
|
||||
/** Content for the right side of the header */
|
||||
headerRight?: ReactNode;
|
||||
/**
|
||||
* body (sub-)header section. If a `string` is used, then it will be wrapped with
|
||||
* `<EuiTitle><h2></h2></EuiTitle>`
|
||||
*/
|
||||
bodyHeader?: ReactNode;
|
||||
/**
|
||||
* The list of tab navigation items
|
||||
*/
|
||||
tabs?: Array<
|
||||
EuiTabProps & {
|
||||
name: ReactNode;
|
||||
id: string;
|
||||
href?: string;
|
||||
onClick?: MouseEventHandler<HTMLAnchorElement | HTMLButtonElement>;
|
||||
}
|
||||
>;
|
||||
children?: ReactNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Page View layout for use in Endpoint
|
||||
*/
|
||||
export const PageView = memo<PageViewProps>(
|
||||
({ viewType, children, headerLeft, headerRight, bodyHeader, tabs, ...otherProps }) => {
|
||||
const tabComponents = useMemo(() => {
|
||||
if (!tabs) {
|
||||
return [];
|
||||
}
|
||||
return tabs.map(({ name, id, ...otherEuiTabProps }) => (
|
||||
<EuiTab {...otherEuiTabProps} key={id}>
|
||||
{name}
|
||||
</EuiTab>
|
||||
));
|
||||
}, [tabs]);
|
||||
|
||||
return (
|
||||
<StyledEuiPage
|
||||
className={(viewType === 'list' && 'endpoint--isListView') || 'endpoint--isDetailsView'}
|
||||
{...otherProps}
|
||||
>
|
||||
<EuiPageBody>
|
||||
{(headerLeft || headerRight) && (
|
||||
<EuiPageHeader className="endpoint-header">
|
||||
<EuiPageHeaderSection
|
||||
className="endpoint-header-leftSection"
|
||||
data-test-subj="pageViewHeaderLeft"
|
||||
>
|
||||
{isStringOrNumber.test(typeof headerLeft) ? (
|
||||
<PageViewHeaderTitle>{headerLeft}</PageViewHeaderTitle>
|
||||
) : (
|
||||
headerLeft
|
||||
)}
|
||||
</EuiPageHeaderSection>
|
||||
{headerRight && (
|
||||
<EuiPageHeaderSection data-test-subj="pageViewHeaderRight">
|
||||
{headerRight}
|
||||
</EuiPageHeaderSection>
|
||||
)}
|
||||
</EuiPageHeader>
|
||||
)}
|
||||
{tabComponents.length > 0 && (
|
||||
<EuiTabs className="endpoint-navTabs">{tabComponents}</EuiTabs>
|
||||
)}
|
||||
<EuiPageContent className="endpoint-page-content">
|
||||
{bodyHeader && (
|
||||
<EuiPageContentHeader>
|
||||
<EuiPageContentHeaderSection data-test-subj="pageViewBodyTitleArea">
|
||||
{isStringOrNumber.test(typeof bodyHeader) ? (
|
||||
<PageViewBodyHeaderTitle>{bodyHeader}</PageViewBodyHeaderTitle>
|
||||
) : (
|
||||
bodyHeader
|
||||
)}
|
||||
</EuiPageContentHeaderSection>
|
||||
</EuiPageContentHeader>
|
||||
)}
|
||||
<EuiPageContentBody data-test-subj="pageViewBodyContent">{children}</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
</EuiPageBody>
|
||||
</StyledEuiPage>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
PageView.displayName = 'PageView';
|
|
@ -7,14 +7,15 @@
|
|||
import classNames from 'classnames';
|
||||
import React, { useEffect } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { CommonProps } from '@elastic/eui';
|
||||
|
||||
import { useFullScreen } from '../../containers/use_full_screen';
|
||||
import { gutterTimeline } from '../../lib/helpers';
|
||||
import { AppGlobalStyle } from '../page/index';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
padding: ${({ theme }) =>
|
||||
`${theme.eui.paddingSizes.l} ${gutterTimeline} ${theme.eui.paddingSizes.l} ${theme.eui.paddingSizes.l}`};
|
||||
padding: ${(props) => `${props.theme.eui.paddingSizes.l}`};
|
||||
|
||||
&.siemWrapperPage--restrictWidthDefault,
|
||||
&.siemWrapperPage--restrictWidthCustom {
|
||||
box-sizing: content-box;
|
||||
|
@ -29,6 +30,10 @@ const Wrapper = styled.div`
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
&.siemWrapperPage--withTimeline {
|
||||
padding-right: ${gutterTimeline};
|
||||
}
|
||||
|
||||
&.siemWrapperPage--noPadding {
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -38,18 +43,20 @@ Wrapper.displayName = 'Wrapper';
|
|||
|
||||
interface WrapperPageProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
restrictWidth?: boolean | number | string;
|
||||
style?: Record<string, string>;
|
||||
noPadding?: boolean;
|
||||
noTimeline?: boolean;
|
||||
}
|
||||
|
||||
const WrapperPageComponent: React.FC<WrapperPageProps> = ({
|
||||
const WrapperPageComponent: React.FC<WrapperPageProps & CommonProps> = ({
|
||||
children,
|
||||
className,
|
||||
restrictWidth,
|
||||
style,
|
||||
noPadding,
|
||||
noTimeline,
|
||||
...otherProps
|
||||
}) => {
|
||||
const { globalFullScreen, setGlobalFullScreen } = useFullScreen();
|
||||
useEffect(() => {
|
||||
|
@ -59,6 +66,7 @@ const WrapperPageComponent: React.FC<WrapperPageProps> = ({
|
|||
const classes = classNames(className, {
|
||||
siemWrapperPage: true,
|
||||
'siemWrapperPage--noPadding': noPadding,
|
||||
'siemWrapperPage--withTimeline': !noTimeline,
|
||||
'siemWrapperPage--fullHeight': globalFullScreen,
|
||||
'siemWrapperPage--restrictWidthDefault':
|
||||
restrictWidth && typeof restrictWidth === 'boolean' && restrictWidth === true,
|
||||
|
@ -73,7 +81,7 @@ const WrapperPageComponent: React.FC<WrapperPageProps> = ({
|
|||
}
|
||||
|
||||
return (
|
||||
<Wrapper className={classes} style={customStyle || style}>
|
||||
<Wrapper className={classes} style={customStyle || style} {...otherProps}>
|
||||
{children}
|
||||
<AppGlobalStyle />
|
||||
</Wrapper>
|
||||
|
|
|
@ -13,6 +13,7 @@ export const MANAGEMENT_ROUTING_ROOT_PATH = '';
|
|||
export const MANAGEMENT_ROUTING_ENDPOINTS_PATH = `${MANAGEMENT_ROUTING_ROOT_PATH}/:tabName(${AdministrationSubTab.endpoints})`;
|
||||
export const MANAGEMENT_ROUTING_POLICIES_PATH = `${MANAGEMENT_ROUTING_ROOT_PATH}/:tabName(${AdministrationSubTab.policies})`;
|
||||
export const MANAGEMENT_ROUTING_POLICY_DETAILS_PATH = `${MANAGEMENT_ROUTING_ROOT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId`;
|
||||
export const MANAGEMENT_ROUTING_TRUSTED_APPS_PATH = `${MANAGEMENT_ROUTING_ROOT_PATH}/:tabName(${AdministrationSubTab.trustedApps})`;
|
||||
|
||||
// --[ STORE ]---------------------------------------------------------------------------
|
||||
/** The SIEM global store namespace where the management state will be mounted */
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
MANAGEMENT_ROUTING_ENDPOINTS_PATH,
|
||||
MANAGEMENT_ROUTING_POLICIES_PATH,
|
||||
MANAGEMENT_ROUTING_POLICY_DETAILS_PATH,
|
||||
MANAGEMENT_ROUTING_TRUSTED_APPS_PATH,
|
||||
} from './constants';
|
||||
import { AdministrationSubTab } from '../types';
|
||||
import { appendSearch } from '../../common/components/link_to/helpers';
|
||||
|
@ -72,13 +73,21 @@ export const getEndpointDetailsPath = (
|
|||
})}${appendSearch(`${urlQueryParams ? `${urlQueryParams}${urlSearch}` : urlSearch}`)}`;
|
||||
};
|
||||
|
||||
export const getPoliciesPath = (search?: string) =>
|
||||
`${generatePath(MANAGEMENT_ROUTING_POLICIES_PATH, {
|
||||
export const getPoliciesPath = (search?: string) => {
|
||||
return `${generatePath(MANAGEMENT_ROUTING_POLICIES_PATH, {
|
||||
tabName: AdministrationSubTab.policies,
|
||||
})}${appendSearch(search)}`;
|
||||
};
|
||||
|
||||
export const getPolicyDetailPath = (policyId: string, search?: string) =>
|
||||
`${generatePath(MANAGEMENT_ROUTING_POLICY_DETAILS_PATH, {
|
||||
export const getPolicyDetailPath = (policyId: string, search?: string) => {
|
||||
return `${generatePath(MANAGEMENT_ROUTING_POLICY_DETAILS_PATH, {
|
||||
tabName: AdministrationSubTab.policies,
|
||||
policyId,
|
||||
})}${appendSearch(search)}`;
|
||||
};
|
||||
|
||||
export const getTrustedAppsListPath = (search?: string) => {
|
||||
return `${generatePath(MANAGEMENT_ROUTING_TRUSTED_APPS_PATH, {
|
||||
tabName: AdministrationSubTab.trustedApps,
|
||||
})}${appendSearch(search)}`;
|
||||
};
|
||||
|
|
|
@ -13,3 +13,11 @@ export const ENDPOINTS_TAB = i18n.translate('xpack.securitySolution.endpointsTab
|
|||
export const POLICIES_TAB = i18n.translate('xpack.securitySolution.policiesTab', {
|
||||
defaultMessage: 'Policies',
|
||||
});
|
||||
|
||||
export const TRUSTED_APPS_TAB = i18n.translate('xpack.securitySolution.trustedAppsTab', {
|
||||
defaultMessage: 'Trusted applications',
|
||||
});
|
||||
|
||||
export const BETA_BADGE_LABEL = i18n.translate('xpack.securitySolution.administration.list.beta', {
|
||||
defaultMessage: 'Beta',
|
||||
});
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import React, { FC, memo } from 'react';
|
||||
import { EuiPanel, EuiSpacer, CommonProps } from '@elastic/eui';
|
||||
import { SecurityPageName } from '../../../common/constants';
|
||||
import { WrapperPage } from '../../common/components/wrapper_page';
|
||||
import { HeaderPage } from '../../common/components/header_page';
|
||||
import { SiemNavigation } from '../../common/components/navigation';
|
||||
import { SpyRoute } from '../../common/utils/route/spy_routes';
|
||||
import { AdministrationSubTab } from '../types';
|
||||
import { ENDPOINTS_TAB, TRUSTED_APPS_TAB, BETA_BADGE_LABEL } from '../common/translations';
|
||||
import { getEndpointListPath, getTrustedAppsListPath } from '../common/routing';
|
||||
|
||||
interface AdministrationListPageProps {
|
||||
beta: boolean;
|
||||
title: React.ReactNode;
|
||||
subtitle: React.ReactNode;
|
||||
actions?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const AdministrationListPage: FC<AdministrationListPageProps & CommonProps> = memo(
|
||||
({ beta, title, subtitle, actions, children, ...otherProps }) => {
|
||||
const badgeOptions = !beta ? undefined : { beta: true, text: BETA_BADGE_LABEL };
|
||||
|
||||
return (
|
||||
<WrapperPage noTimeline {...otherProps}>
|
||||
<HeaderPage title={title} subtitle={subtitle} badgeOptions={badgeOptions}>
|
||||
{actions}
|
||||
</HeaderPage>
|
||||
|
||||
<SiemNavigation
|
||||
navTabs={{
|
||||
[AdministrationSubTab.endpoints]: {
|
||||
name: ENDPOINTS_TAB,
|
||||
id: AdministrationSubTab.endpoints,
|
||||
href: getEndpointListPath({ name: 'endpointList' }),
|
||||
urlKey: 'administration',
|
||||
pageId: SecurityPageName.administration,
|
||||
disabled: false,
|
||||
},
|
||||
[AdministrationSubTab.trustedApps]: {
|
||||
name: TRUSTED_APPS_TAB,
|
||||
id: AdministrationSubTab.trustedApps,
|
||||
href: getTrustedAppsListPath(),
|
||||
urlKey: 'administration',
|
||||
pageId: SecurityPageName.administration,
|
||||
disabled: false,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiPanel>{children}</EuiPanel>
|
||||
|
||||
<SpyRoute pageName={SecurityPageName.administration} />
|
||||
</WrapperPage>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
AdministrationListPage.displayName = 'AdministrationListPage';
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import { EuiErrorBoundary } from '@elastic/eui';
|
||||
import { PageView, PageViewProps } from '../../common/components/endpoint/page_view';
|
||||
|
||||
export const ManagementPageView = memo<Omit<PageViewProps, 'tabs'>>((options) => {
|
||||
return (
|
||||
<EuiErrorBoundary>
|
||||
<PageView {...options} />
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
});
|
||||
|
||||
ManagementPageView.displayName = 'ManagementPageView';
|
|
@ -8,6 +8,7 @@ import React from 'react';
|
|||
import * as reactTestingLibrary from '@testing-library/react';
|
||||
|
||||
import { EndpointList } from './index';
|
||||
import '../../../../common/mock/match_media.ts';
|
||||
import {
|
||||
mockEndpointDetailsApiResult,
|
||||
mockEndpointResultList,
|
||||
|
|
|
@ -10,15 +10,10 @@ import {
|
|||
EuiBasicTable,
|
||||
EuiBasicTableColumn,
|
||||
EuiText,
|
||||
EuiTitle,
|
||||
EuiSpacer,
|
||||
EuiLink,
|
||||
EuiHealth,
|
||||
EuiToolTip,
|
||||
EuiSelectableProps,
|
||||
EuiBetaBadge,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
} from '@elastic/eui';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -36,8 +31,6 @@ import {
|
|||
import { useNavigateByRouterEventHandler } from '../../../../common/hooks/endpoint/use_navigate_by_router_event_handler';
|
||||
import { CreateStructuredSelector } from '../../../../common/store';
|
||||
import { Immutable, HostInfo } from '../../../../../common/endpoint/types';
|
||||
import { SpyRoute } from '../../../../common/utils/route/spy_routes';
|
||||
import { ManagementPageView } from '../../../components/management_page_view';
|
||||
import { PolicyEmptyState, HostsEmptyState } from '../../../components/management_empty_state';
|
||||
import { FormattedDate } from '../../../../common/components/formatted_date';
|
||||
import { useNavigateToAppEventHandler } from '../../../../common/hooks/endpoint/use_navigate_to_app_event_handler';
|
||||
|
@ -50,6 +43,7 @@ import { getEndpointListPath, getEndpointDetailsPath } from '../../../common/rou
|
|||
import { useFormatUrl } from '../../../../common/components/link_to';
|
||||
import { EndpointAction } from '../store/action';
|
||||
import { EndpointPolicyLink } from './components/endpoint_policy_link';
|
||||
import { AdministrationListPage } from '../../../components/administration_list_page';
|
||||
|
||||
const EndpointListNavLink = memo<{
|
||||
name: string;
|
||||
|
@ -375,40 +369,20 @@ export const EndpointList = () => {
|
|||
]);
|
||||
|
||||
return (
|
||||
<ManagementPageView
|
||||
viewType="list"
|
||||
<AdministrationListPage
|
||||
data-test-subj="endpointPage"
|
||||
headerLeft={
|
||||
<>
|
||||
<EuiFlexGroup alignItems="center" responsive={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle size="l">
|
||||
<h1 data-test-subj="pageViewHeaderLeftTitle">
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.endpoint.list.pageTitle"
|
||||
defaultMessage="Endpoints"
|
||||
/>
|
||||
</h1>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiBetaBadge
|
||||
label={i18n.translate('xpack.securitySolution.endpoint.list.beta', {
|
||||
defaultMessage: 'Beta',
|
||||
})}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiText size="s" color="subdued">
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.endpoint.list.pageSubTitle"
|
||||
defaultMessage="Hosts running Elastic Endpoint Security"
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
</>
|
||||
beta={true}
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.endpoint.list.pageTitle"
|
||||
defaultMessage="Endpoints"
|
||||
/>
|
||||
}
|
||||
subtitle={
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.endpoint.list.pageSubTitle"
|
||||
defaultMessage="Hosts running Elastic Endpoint Security"
|
||||
/>
|
||||
}
|
||||
>
|
||||
{hasSelectedEndpoint && <EndpointDetailsFlyout />}
|
||||
|
@ -425,7 +399,6 @@ export const EndpointList = () => {
|
|||
</>
|
||||
)}
|
||||
{renderTableOrEmptyState}
|
||||
<SpyRoute pageName={SecurityPageName.administration} />
|
||||
</ManagementPageView>
|
||||
</AdministrationListPage>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import { ManagementContainer } from './index';
|
||||
import '../../common/mock/match_media.ts';
|
||||
import { AppContextTestRender, createAppRootMockRenderer } from '../../common/mock/endpoint';
|
||||
import { useIngestEnabledCheck } from '../../common/hooks/endpoint/ingest_enabled';
|
||||
|
||||
|
@ -22,15 +23,13 @@ describe('when in the Admistration tab', () => {
|
|||
|
||||
it('should display the No Permissions view when Ingest is OFF', async () => {
|
||||
(useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: false });
|
||||
const renderResult = render();
|
||||
const noIngestPermissions = await renderResult.findByTestId('noIngestPermissions');
|
||||
expect(noIngestPermissions).not.toBeNull();
|
||||
|
||||
expect(await render().findByTestId('noIngestPermissions')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should display the Management view when Ingest is ON', async () => {
|
||||
(useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: true });
|
||||
const renderResult = render();
|
||||
const endpointPage = await renderResult.findByTestId('endpointPage');
|
||||
expect(endpointPage).not.toBeNull();
|
||||
|
||||
expect(await render().findByTestId('endpointPage')).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,55 +11,50 @@ import { useHistory, Route, Switch } from 'react-router-dom';
|
|||
import { ChromeBreadcrumb } from 'kibana/public';
|
||||
import { EuiText, EuiEmptyPrompt } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { PolicyContainer } from './policy';
|
||||
import {
|
||||
MANAGEMENT_ROUTING_ENDPOINTS_PATH,
|
||||
MANAGEMENT_ROUTING_POLICIES_PATH,
|
||||
MANAGEMENT_ROUTING_ROOT_PATH,
|
||||
MANAGEMENT_ROUTING_TRUSTED_APPS_PATH,
|
||||
} from '../common/constants';
|
||||
import { NotFoundPage } from '../../app/404';
|
||||
import { EndpointsContainer } from './endpoint_hosts';
|
||||
import { PolicyContainer } from './policy';
|
||||
import { TrustedAppsContainer } from './trusted_apps';
|
||||
import { getEndpointListPath } from '../common/routing';
|
||||
import { APP_ID, SecurityPageName } from '../../../common/constants';
|
||||
import { GetUrlForApp } from '../../common/components/navigation/types';
|
||||
import { AdministrationRouteSpyState } from '../../common/utils/route/types';
|
||||
import { ADMINISTRATION } from '../../app/home/translations';
|
||||
import { AdministrationSubTab } from '../types';
|
||||
import { ENDPOINTS_TAB, POLICIES_TAB } from '../common/translations';
|
||||
import { ENDPOINTS_TAB, POLICIES_TAB, TRUSTED_APPS_TAB } from '../common/translations';
|
||||
import { SpyRoute } from '../../common/utils/route/spy_routes';
|
||||
import { useIngestEnabledCheck } from '../../common/hooks/endpoint/ingest_enabled';
|
||||
|
||||
const TabNameMappedToI18nKey: Record<string, string> = {
|
||||
const TabNameMappedToI18nKey: Record<AdministrationSubTab, string> = {
|
||||
[AdministrationSubTab.endpoints]: ENDPOINTS_TAB,
|
||||
[AdministrationSubTab.policies]: POLICIES_TAB,
|
||||
[AdministrationSubTab.trustedApps]: TRUSTED_APPS_TAB,
|
||||
};
|
||||
|
||||
export const getBreadcrumbs = (
|
||||
export function getBreadcrumbs(
|
||||
params: AdministrationRouteSpyState,
|
||||
search: string[],
|
||||
getUrlForApp: GetUrlForApp
|
||||
): ChromeBreadcrumb[] => {
|
||||
let breadcrumb = [
|
||||
): ChromeBreadcrumb[] {
|
||||
return [
|
||||
{
|
||||
text: ADMINISTRATION,
|
||||
href: getUrlForApp(`${APP_ID}:${SecurityPageName.administration}`, {
|
||||
path: !isEmpty(search[0]) ? search[0] : '',
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
||||
const tabName = params?.tabName;
|
||||
if (!tabName) return breadcrumb;
|
||||
|
||||
breadcrumb = [
|
||||
...breadcrumb,
|
||||
{
|
||||
...(params?.tabName ? [params?.tabName] : []).map((tabName) => ({
|
||||
text: TabNameMappedToI18nKey[tabName],
|
||||
href: '',
|
||||
},
|
||||
})),
|
||||
];
|
||||
return breadcrumb;
|
||||
};
|
||||
}
|
||||
|
||||
const NoPermissions = memo(() => {
|
||||
return (
|
||||
|
@ -104,6 +99,7 @@ export const ManagementContainer = memo(() => {
|
|||
<Switch>
|
||||
<Route path={MANAGEMENT_ROUTING_ENDPOINTS_PATH} component={EndpointsContainer} />
|
||||
<Route path={MANAGEMENT_ROUTING_POLICIES_PATH} component={PolicyContainer} />
|
||||
<Route path={MANAGEMENT_ROUTING_TRUSTED_APPS_PATH} component={TrustedAppsContainer} />
|
||||
<Route
|
||||
path={MANAGEMENT_ROUTING_ROOT_PATH}
|
||||
exact
|
||||
|
|
|
@ -8,6 +8,7 @@ import React from 'react';
|
|||
import { mount } from 'enzyme';
|
||||
|
||||
import { PolicyDetails } from './policy_details';
|
||||
import '../../../../common/mock/match_media.ts';
|
||||
import { EndpointDocGenerator } from '../../../../../common/endpoint/generate_data';
|
||||
import { AppContextTestRender, createAppRootMockRenderer } from '../../../../common/mock/endpoint';
|
||||
import { getPolicyDetailPath, getEndpointListPath } from '../../../common/routing';
|
||||
|
@ -123,35 +124,29 @@ describe('Policy Details', () => {
|
|||
|
||||
it('should display back to list button and policy title', () => {
|
||||
policyView.update();
|
||||
const pageHeaderLeft = policyView.find(
|
||||
'EuiPageHeaderSection[data-test-subj="pageViewHeaderLeft"]'
|
||||
);
|
||||
|
||||
const backToListButton = pageHeaderLeft.find('EuiButtonEmpty');
|
||||
expect(backToListButton.prop('iconType')).toBe('arrowLeft');
|
||||
expect(backToListButton.prop('href')).toBe(endpointListPath);
|
||||
expect(backToListButton.text()).toBe('Back to endpoint hosts');
|
||||
const backToListLink = policyView.find('LinkIcon[dataTestSubj="policyDetailsBackLink"]');
|
||||
expect(backToListLink.prop('iconType')).toBe('arrowLeft');
|
||||
expect(backToListLink.prop('href')).toBe(endpointListPath);
|
||||
expect(backToListLink.text()).toBe('Back to endpoint hosts');
|
||||
|
||||
const pageTitle = pageHeaderLeft.find('[data-test-subj="pageViewHeaderLeftTitle"]');
|
||||
const pageTitle = policyView.find('h1[data-test-subj="header-page-title"]');
|
||||
expect(pageTitle).toHaveLength(1);
|
||||
expect(pageTitle.text()).toEqual(policyPackageConfig.name);
|
||||
});
|
||||
it('should navigate to list if back to link is clicked', async () => {
|
||||
policyView.update();
|
||||
const backToListButton = policyView.find(
|
||||
'EuiPageHeaderSection[data-test-subj="pageViewHeaderLeft"] EuiButtonEmpty'
|
||||
);
|
||||
|
||||
const backToListLink = policyView.find('a[data-test-subj="policyDetailsBackLink"]');
|
||||
expect(history.location.pathname).toEqual(policyDetailsPathUrl);
|
||||
backToListButton.simulate('click', { button: 0 });
|
||||
backToListLink.simulate('click', { button: 0 });
|
||||
expect(history.location.pathname).toEqual(endpointListPath);
|
||||
});
|
||||
it('should display agent stats', async () => {
|
||||
await asyncActions;
|
||||
policyView.update();
|
||||
const headerRight = policyView.find(
|
||||
'EuiPageHeaderSection[data-test-subj="pageViewHeaderRight"]'
|
||||
);
|
||||
const agentsSummary = headerRight.find('EuiFlexGroup[data-test-subj="policyAgentsSummary"]');
|
||||
|
||||
const agentsSummary = policyView.find('EuiFlexGroup[data-test-subj="policyAgentsSummary"]');
|
||||
expect(agentsSummary).toHaveLength(1);
|
||||
expect(agentsSummary.text()).toBe('Endpoints5Online3Offline1Error1');
|
||||
});
|
||||
|
|
|
@ -38,9 +38,6 @@ import { WindowsEvents, MacEvents, LinuxEvents } from './policy_forms/events';
|
|||
import { MalwareProtections } from './policy_forms/protections/malware';
|
||||
import { useToasts } from '../../../../common/lib/kibana';
|
||||
import { AppAction } from '../../../../common/store/actions';
|
||||
import { useNavigateByRouterEventHandler } from '../../../../common/hooks/endpoint/use_navigate_by_router_event_handler';
|
||||
import { PageViewHeaderTitle } from '../../../../common/components/endpoint/page_view';
|
||||
import { ManagementPageView } from '../../../components/management_page_view';
|
||||
import { SpyRoute } from '../../../../common/utils/route/spy_routes';
|
||||
import { SecurityPageName } from '../../../../app/types';
|
||||
import { getEndpointListPath } from '../../../common/routing';
|
||||
|
@ -48,6 +45,8 @@ import { useFormatUrl } from '../../../../common/components/link_to';
|
|||
import { useNavigateToAppEventHandler } from '../../../../common/hooks/endpoint/use_navigate_to_app_event_handler';
|
||||
import { MANAGEMENT_APP_ID } from '../../../common/constants';
|
||||
import { PolicyDetailsRouteState } from '../../../../../common/endpoint/types';
|
||||
import { WrapperPage } from '../../../../common/components/wrapper_page';
|
||||
import { HeaderPage } from '../../../../common/components/header_page';
|
||||
|
||||
export const PolicyDetails = React.memo(() => {
|
||||
const dispatch = useDispatch<(action: AppAction) => void>();
|
||||
|
@ -109,8 +108,6 @@ export const PolicyDetails = React.memo(() => {
|
|||
}
|
||||
}, [navigateToApp, toasts, policyName, policyUpdateStatus, routeState]);
|
||||
|
||||
const handleBackToListOnClick = useNavigateByRouterEventHandler(hostListRouterPath);
|
||||
|
||||
const navigateToAppArguments = useMemo((): Parameters<ApplicationStart['navigateToApp']> => {
|
||||
return routeState?.onCancelNavigateTo ?? [MANAGEMENT_APP_ID, { path: hostListRouterPath }];
|
||||
}, [hostListRouterPath, routeState?.onCancelNavigateTo]);
|
||||
|
@ -142,7 +139,7 @@ export const PolicyDetails = React.memo(() => {
|
|||
// Else, if we have an error, then show error on the page.
|
||||
if (!policyItem) {
|
||||
return (
|
||||
<ManagementPageView viewType="details">
|
||||
<WrapperPage noTimeline>
|
||||
{isPolicyLoading ? (
|
||||
<EuiLoadingSpinner size="xl" />
|
||||
) : policyApiError ? (
|
||||
|
@ -151,28 +148,10 @@ export const PolicyDetails = React.memo(() => {
|
|||
</EuiCallOut>
|
||||
) : null}
|
||||
<SpyRoute pageName={SecurityPageName.administration} />
|
||||
</ManagementPageView>
|
||||
</WrapperPage>
|
||||
);
|
||||
}
|
||||
|
||||
const headerLeftContent = (
|
||||
<div>
|
||||
{/* eslint-disable-next-line @elastic/eui/href-or-on-click */}
|
||||
<EuiButtonEmpty
|
||||
iconType="arrowLeft"
|
||||
contentProps={{ style: { paddingLeft: '0' } }}
|
||||
onClick={handleBackToListOnClick}
|
||||
href={formatUrl(hostListRouterPath)}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.endpoint.policy.details.backToListTitle"
|
||||
defaultMessage="Back to endpoint hosts"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
<PageViewHeaderTitle className="eui-textTruncate">{policyItem.name}</PageViewHeaderTitle>
|
||||
</div>
|
||||
);
|
||||
|
||||
const headerRightContent = (
|
||||
<EuiFlexGroup justifyContent="flexEnd" gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
|
@ -222,12 +201,21 @@ export const PolicyDetails = React.memo(() => {
|
|||
onConfirm={handleSaveConfirmation}
|
||||
/>
|
||||
)}
|
||||
<ManagementPageView
|
||||
viewType="details"
|
||||
data-test-subj="policyDetailsPage"
|
||||
headerLeft={headerLeftContent}
|
||||
headerRight={headerRightContent}
|
||||
>
|
||||
<WrapperPage noTimeline data-test-subj="policyDetailsPage">
|
||||
<HeaderPage
|
||||
title={policyItem.name}
|
||||
backOptions={{
|
||||
text: i18n.translate('xpack.securitySolution.endpoint.policy.details.backToListTitle', {
|
||||
defaultMessage: 'Back to endpoint hosts',
|
||||
}),
|
||||
href: formatUrl(hostListRouterPath),
|
||||
pageId: SecurityPageName.administration,
|
||||
dataTestSubj: 'policyDetailsBackLink',
|
||||
}}
|
||||
>
|
||||
{headerRightContent}
|
||||
</HeaderPage>
|
||||
|
||||
<EuiText size="xs" color="subdued">
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
|
@ -236,9 +224,11 @@ export const PolicyDetails = React.memo(() => {
|
|||
/>
|
||||
</h4>
|
||||
</EuiText>
|
||||
|
||||
<EuiSpacer size="xs" />
|
||||
<MalwareProtections />
|
||||
<EuiSpacer size="l" />
|
||||
|
||||
<EuiText size="xs" color="subdued">
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
|
@ -247,13 +237,15 @@ export const PolicyDetails = React.memo(() => {
|
|||
/>
|
||||
</h4>
|
||||
</EuiText>
|
||||
|
||||
<EuiSpacer size="xs" />
|
||||
<WindowsEvents />
|
||||
<EuiSpacer size="l" />
|
||||
<MacEvents />
|
||||
<EuiSpacer size="l" />
|
||||
<LinuxEvents />
|
||||
</ManagementPageView>
|
||||
</WrapperPage>
|
||||
|
||||
<SpyRoute pageName={SecurityPageName.administration} />
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import { PolicyList } from './index';
|
||||
import '../../../../common/mock/match_media.ts';
|
||||
import { AppContextTestRender, createAppRootMockRenderer } from '../../../../common/mock/endpoint';
|
||||
import { setPolicyListApiMockImplementation } from '../store/policy_list/test_mock_utils';
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import React, { useCallback, useEffect, useMemo, CSSProperties, useState } from
|
|||
import {
|
||||
EuiBasicTable,
|
||||
EuiText,
|
||||
EuiTitle,
|
||||
EuiSpacer,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
|
@ -23,7 +22,6 @@ import {
|
|||
EuiConfirmModal,
|
||||
EuiCallOut,
|
||||
EuiButton,
|
||||
EuiBetaBadge,
|
||||
EuiHorizontalRule,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -41,9 +39,7 @@ import { useKibana } from '../../../../../../../../src/plugins/kibana_react/publ
|
|||
import { Immutable, PolicyData } from '../../../../../common/endpoint/types';
|
||||
import { useNavigateByRouterEventHandler } from '../../../../common/hooks/endpoint/use_navigate_by_router_event_handler';
|
||||
import { LinkToApp } from '../../../../common/components/endpoint/link_to_app';
|
||||
import { ManagementPageView } from '../../../components/management_page_view';
|
||||
import { PolicyEmptyState } from '../../../components/management_empty_state';
|
||||
import { SpyRoute } from '../../../../common/utils/route/spy_routes';
|
||||
import { FormattedDateAndTime } from '../../../../common/components/endpoint/formatted_date_time';
|
||||
import { SecurityPageName } from '../../../../app/types';
|
||||
import { useFormatUrl } from '../../../../common/components/link_to';
|
||||
|
@ -51,6 +47,7 @@ import { getPolicyDetailPath, getPoliciesPath } from '../../../common/routing';
|
|||
import { useNavigateToAppEventHandler } from '../../../../common/hooks/endpoint/use_navigate_to_app_event_handler';
|
||||
import { CreatePackageConfigRouteState } from '../../../../../../ingest_manager/public';
|
||||
import { MANAGEMENT_APP_ID } from '../../../common/constants';
|
||||
import { AdministrationListPage } from '../../../components/administration_list_page';
|
||||
|
||||
interface TableChangeCallbackArguments {
|
||||
page: { index: number; size: number };
|
||||
|
@ -405,42 +402,22 @@ export const PolicyList = React.memo(() => {
|
|||
}}
|
||||
/>
|
||||
)}
|
||||
<ManagementPageView
|
||||
viewType="list"
|
||||
<AdministrationListPage
|
||||
data-test-subj="policyListPage"
|
||||
headerLeft={
|
||||
<>
|
||||
<EuiFlexGroup alignItems="center" responsive={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle size="l">
|
||||
<h1 data-test-subj="pageViewHeaderLeftTitle">
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.policyList.pageTitle"
|
||||
defaultMessage="Policies"
|
||||
/>
|
||||
</h1>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiBetaBadge
|
||||
label={i18n.translate('xpack.securitySolution.endpoint.policyList.beta', {
|
||||
defaultMessage: 'Beta',
|
||||
})}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiText size="s" color="subdued">
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.policyList.pageSubTitle"
|
||||
defaultMessage="View and configure protections"
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
</>
|
||||
beta={true}
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.policyList.pageTitle"
|
||||
defaultMessage="Policies"
|
||||
/>
|
||||
}
|
||||
headerRight={
|
||||
subtitle={
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.policyList.pageSubTitle"
|
||||
defaultMessage="View and configure protections"
|
||||
/>
|
||||
}
|
||||
actions={
|
||||
<EuiButton
|
||||
iconType="plusInCircle"
|
||||
onClick={handleCreatePolicyClick}
|
||||
|
@ -466,8 +443,7 @@ export const PolicyList = React.memo(() => {
|
|||
</>
|
||||
)}
|
||||
{bodyContent}
|
||||
<SpyRoute pageName={SecurityPageName.administration} />
|
||||
</ManagementPageView>
|
||||
</AdministrationListPage>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import React from 'react';
|
||||
import { TrustedAppsPage } from './view';
|
||||
import { MANAGEMENT_ROUTING_TRUSTED_APPS_PATH } from '../../common/constants';
|
||||
import { NotFoundPage } from '../../../app/404';
|
||||
|
||||
export function TrustedAppsContainer() {
|
||||
return (
|
||||
<Switch>
|
||||
<Route path={MANAGEMENT_ROUTING_TRUSTED_APPS_PATH} exact component={TrustedAppsPage} />
|
||||
<Route path="*" component={NotFoundPage} />
|
||||
</Switch>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TrustedAppsPage rendering 1`] = `
|
||||
<AdministrationListPage
|
||||
beta={true}
|
||||
subtitle={
|
||||
<FormattedMessage
|
||||
defaultMessage="View and configure trusted applications"
|
||||
id="xpack.securitySolution.trustedapps.list.pageSubTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
title={
|
||||
<FormattedMessage
|
||||
defaultMessage="Trusted Applications"
|
||||
id="xpack.securitySolution.trustedapps.list.pageTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
`;
|
|
@ -0,0 +1,6 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
export * from './trusted_apps_page';
|
|
@ -3,16 +3,13 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
|
||||
import { EndpointList } from './view';
|
||||
import { TrustedAppsPage } from './trusted_apps_page';
|
||||
|
||||
export const EndpointHostsRoutes: React.FC = () => (
|
||||
<Switch>
|
||||
<Route path="/:pageName(endpoint-endpoints)">
|
||||
<EndpointList />
|
||||
</Route>
|
||||
</Switch>
|
||||
);
|
||||
describe('TrustedAppsPage', () => {
|
||||
test('rendering', () => {
|
||||
expect(shallow(<TrustedAppsPage />)).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { AdministrationListPage } from '../../../components/administration_list_page';
|
||||
|
||||
export function TrustedAppsPage() {
|
||||
return (
|
||||
<AdministrationListPage
|
||||
beta={true}
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.trustedapps.list.pageTitle"
|
||||
defaultMessage="Trusted Applications"
|
||||
/>
|
||||
}
|
||||
subtitle={
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.trustedapps.list.pageSubTitle"
|
||||
defaultMessage="View and configure trusted applications"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -27,6 +27,7 @@ export type ManagementState = CombinedState<{
|
|||
export enum AdministrationSubTab {
|
||||
endpoints = 'endpoints',
|
||||
policies = 'policy',
|
||||
trustedApps = 'trusted_apps',
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16266,7 +16266,6 @@
|
|||
"xpack.securitySolution.endpoint.details.policyResponse.success": "成功",
|
||||
"xpack.securitySolution.endpoint.details.policyResponse.warning": "警告",
|
||||
"xpack.securitySolution.endpoint.details.policyResponse.workflow": "ワークフロー",
|
||||
"xpack.securitySolution.endpoint.list.beta": "ベータ",
|
||||
"xpack.securitySolution.endpoint.list.loadingPolicies": "ポリシー構成を読み込んでいます…",
|
||||
"xpack.securitySolution.endpoint.list.noEndpointsInstructions": "セキュリティポリシーを作成しました。以下のステップに従い、エージェントでElastic Endpoint Security機能を有効にする必要があります。",
|
||||
"xpack.securitySolution.endpoint.list.noEndpointsPrompt": "エージェントでElastic Endpoint Securityを有効にする",
|
||||
|
@ -16328,7 +16327,6 @@
|
|||
"xpack.securitySolution.endpoint.policyList.actionButtonText": "Endpoint Securityを追加",
|
||||
"xpack.securitySolution.endpoint.policyList.actionMenu": "開く",
|
||||
"xpack.securitySolution.endpoint.policyList.agentConfigAction": "エージェント構成を表示",
|
||||
"xpack.securitySolution.endpoint.policyList.beta": "ベータ",
|
||||
"xpack.securitySolution.endpoint.policyList.createdAt": "作成日時",
|
||||
"xpack.securitySolution.endpoint.policyList.createdBy": "作成者",
|
||||
"xpack.securitySolution.endpoint.policyList.createNewButton": "新しいポリシーを作成",
|
||||
|
|
|
@ -16272,7 +16272,6 @@
|
|||
"xpack.securitySolution.endpoint.details.policyResponse.success": "成功",
|
||||
"xpack.securitySolution.endpoint.details.policyResponse.warning": "警告",
|
||||
"xpack.securitySolution.endpoint.details.policyResponse.workflow": "工作流",
|
||||
"xpack.securitySolution.endpoint.list.beta": "公测版",
|
||||
"xpack.securitySolution.endpoint.list.loadingPolicies": "正在加载政策配置",
|
||||
"xpack.securitySolution.endpoint.list.noEndpointsInstructions": "您已创建安全策略。现在您需要按照下面的步骤在代理上启用 Elastic Endpoint Security 功能。",
|
||||
"xpack.securitySolution.endpoint.list.noEndpointsPrompt": "在您的代理上启用 Elastic Endpoint Security",
|
||||
|
@ -16335,7 +16334,6 @@
|
|||
"xpack.securitySolution.endpoint.policyList.actionButtonText": "添加 Endpoint Security",
|
||||
"xpack.securitySolution.endpoint.policyList.actionMenu": "打开",
|
||||
"xpack.securitySolution.endpoint.policyList.agentConfigAction": "查看代理配置",
|
||||
"xpack.securitySolution.endpoint.policyList.beta": "公测版",
|
||||
"xpack.securitySolution.endpoint.policyList.createdAt": "创建日期",
|
||||
"xpack.securitySolution.endpoint.policyList.createdBy": "创建者",
|
||||
"xpack.securitySolution.endpoint.policyList.createNewButton": "创建新策略",
|
||||
|
|
|
@ -27,8 +27,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
});
|
||||
|
||||
it('finds page title', async () => {
|
||||
const title = await testSubjects.getVisibleText('pageViewHeaderLeftTitle');
|
||||
expect(title).to.equal('Endpoints');
|
||||
const title = await testSubjects.getVisibleText('header-page-title');
|
||||
expect(title).to.equal('Endpoints BETA');
|
||||
});
|
||||
|
||||
it('displays table data', async () => {
|
||||
|
|
|
@ -47,7 +47,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('should display policy view', async () => {
|
||||
expect(await testSubjects.getVisibleText('pageViewHeaderLeftTitle')).to.equal(
|
||||
expect(await testSubjects.getVisibleText('header-page-title')).to.equal(
|
||||
policyInfo.packageConfig.name
|
||||
);
|
||||
});
|
||||
|
|
|
@ -29,8 +29,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
await testSubjects.existOrFail('policyListPage');
|
||||
});
|
||||
it('displays page title', async () => {
|
||||
const policyTitle = await testSubjects.getVisibleText('pageViewHeaderLeftTitle');
|
||||
expect(policyTitle).to.equal('Policies');
|
||||
const policyTitle = await testSubjects.getVisibleText('header-page-title');
|
||||
expect(policyTitle).to.equal('Policies BETA');
|
||||
});
|
||||
it('shows header create policy button', async () => {
|
||||
const createButtonTitle = await testSubjects.getVisibleText('headerCreateNewPolicyButton');
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
||||
const pageObjects = getPageObjects(['trustedApps']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
||||
describe('endpoint list', function () {
|
||||
this.tags('ciGroup7');
|
||||
|
||||
describe('when there is data', () => {
|
||||
before(async () => {
|
||||
await pageObjects.trustedApps.navigateToTrustedAppsList();
|
||||
});
|
||||
|
||||
it('finds page title', async () => {
|
||||
expect(await testSubjects.getVisibleText('header-page-title')).to.equal(
|
||||
'Trusted applications BETA'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -7,6 +7,7 @@
|
|||
import { pageObjects as xpackFunctionalPageObjects } from '../../functional/page_objects';
|
||||
import { EndpointPageProvider } from './endpoint_page';
|
||||
import { EndpointPolicyPageProvider } from './policy_page';
|
||||
import { TrustedAppsPageProvider } from './trusted_apps_page';
|
||||
import { EndpointPageUtils } from './page_utils';
|
||||
import { IngestManagerCreatePackageConfig } from './ingest_manager_create_package_config_page';
|
||||
|
||||
|
@ -14,6 +15,7 @@ export const pageObjects = {
|
|||
...xpackFunctionalPageObjects,
|
||||
endpoint: EndpointPageProvider,
|
||||
policy: EndpointPolicyPageProvider,
|
||||
trustedApps: TrustedAppsPageProvider,
|
||||
endpointPageUtils: EndpointPageUtils,
|
||||
ingestManagerCreatePackageConfig: IngestManagerCreatePackageConfig,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export function TrustedAppsPageProvider({ getPageObjects }: FtrProviderContext) {
|
||||
const pageObjects = getPageObjects(['common', 'header', 'endpointPageUtils']);
|
||||
|
||||
return {
|
||||
async navigateToTrustedAppsList(searchParams?: string) {
|
||||
await pageObjects.common.navigateToUrlWithBrowserHistory(
|
||||
'securitySolutionManagement',
|
||||
`/trusted_apps${searchParams ? `?${searchParams}` : ''}`
|
||||
);
|
||||
await pageObjects.header.waitUntilLoadingHasFinished();
|
||||
},
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue