Skip to content

Commit babeafd

Browse files
authored
Fleet view search link (stolostron#3511)
* [ACM-11230] Include search link in Fleet View header Signed-off-by: zlayne <zlayne@redhat.com> * fix import Signed-off-by: zlayne <zlayne@redhat.com> * add copyright Signed-off-by: zlayne <zlayne@redhat.com> * Update snapshot test Signed-off-by: zlayne <zlayne@redhat.com> --------- Signed-off-by: zlayne <zlayne@redhat.com>
1 parent 28e9f4f commit babeafd

File tree

8 files changed

+182
-74
lines changed

8 files changed

+182
-74
lines changed

frontend/src/routes/Home/Overview/Overview.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Switch } from '@patternfly/react-core'
33
import { useState } from 'react'
44
import { useTranslation } from '../../../lib/acm-i18next'
55
import { AcmPage, AcmPageHeader } from '../../../ui-components'
6+
import ReuseableSearchbar from '../Search/components/ReuseableSearchbar'
67
import OverviewClusterLabelSelector from './OverviewClusterLabelSelector'
78
import OverviewPage from './OverviewPage'
89
import OverviewPageBeta from './OverviewPageBeta'
@@ -28,6 +29,7 @@ export default function Overview() {
2829
}}
2930
/>
3031
}
32+
searchbar={<ReuseableSearchbar />}
3133
/>
3234
{/* Fleet view includes a cluster label filter */}
3335
{isBetaView && (

frontend/src/routes/Home/Overview/OverviewPage.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -637,9 +637,9 @@ export default function OverviewPage() {
637637
<AcmAlert
638638
noClose
639639
isInline
640-
variant={searchError?.graphQLErrors[0]?.message.includes('not enabled') ? 'info' : 'warning'}
640+
variant={searchError?.graphQLErrors[0]?.message?.includes('not enabled') ? 'info' : 'warning'}
641641
title={
642-
searchError?.graphQLErrors[0]?.message.includes('not enabled')
642+
searchError?.graphQLErrors[0]?.message?.includes('not enabled')
643643
? t('Configuration alert')
644644
: t('An unexpected error occurred.')
645645
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* Copyright Contributors to the Open Cluster Management project */
2+
import { render } from '@testing-library/react'
3+
import { MemoryRouter } from 'react-router-dom'
4+
import { RecoilRoot } from 'recoil'
5+
import { isGlobalHubState, Settings, settingsState } from '../../../../atoms'
6+
import ReuseableSearchbar from './ReuseableSearchbar'
7+
8+
test('renders with default Search link', () => {
9+
const mockSettings: Settings = {
10+
globalSearchFeatureFlag: 'disabled',
11+
}
12+
const { baseElement } = render(
13+
<RecoilRoot
14+
initializeState={(snapshot) => {
15+
snapshot.set(isGlobalHubState, false), snapshot.set(settingsState, mockSettings)
16+
}}
17+
>
18+
<MemoryRouter>
19+
<ReuseableSearchbar />
20+
</MemoryRouter>
21+
</RecoilRoot>
22+
)
23+
expect(baseElement).toMatchSnapshot()
24+
})
25+
26+
test('renders with Global Search link', () => {
27+
const mockSettings: Settings = {
28+
globalSearchFeatureFlag: 'enabled',
29+
}
30+
const { baseElement } = render(
31+
<RecoilRoot
32+
initializeState={(snapshot) => {
33+
snapshot.set(isGlobalHubState, true), snapshot.set(settingsState, mockSettings)
34+
}}
35+
>
36+
<MemoryRouter>
37+
<ReuseableSearchbar />
38+
</MemoryRouter>
39+
</RecoilRoot>
40+
)
41+
expect(baseElement).toMatchSnapshot()
42+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* Copyright Contributors to the Open Cluster Management project */
2+
import { SearchIcon } from '@patternfly/react-icons'
3+
import { Link } from 'react-router-dom'
4+
import { useTranslation } from '../../../../lib/acm-i18next'
5+
import { NavigationPath } from '../../../../NavigationPath'
6+
import { useRecoilValue, useSharedAtoms } from '../../../../shared-recoil'
7+
import { AcmButton } from '../../../../ui-components'
8+
9+
export default function ReuseableSearchbar() {
10+
const { t } = useTranslation()
11+
const { isGlobalHubState, settingsState } = useSharedAtoms()
12+
const isGlobalHub = useRecoilValue(isGlobalHubState)
13+
const settings = useRecoilValue(settingsState)
14+
15+
return (
16+
<Link to={NavigationPath.search}>
17+
<AcmButton variant="link" isInline icon={<SearchIcon />} iconPosition="left">
18+
{isGlobalHub && settings.globalSearchFeatureFlag === 'enabled' ? t('Global search') : t('Search')}
19+
</AcmButton>
20+
</Link>
21+
)
22+
}

frontend/src/routes/Home/Search/components/__snapshots__/HeaderWithNotification.test.tsx.snap

-48
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,6 @@ exports[`renders clusters disabled message 1`] = `
5959
</div>
6060
</div>
6161
</div>
62-
<div
63-
class="pf-l-split__item"
64-
>
65-
<section
66-
class="pf-c-page__main-section pf-m-light"
67-
style="height: 100%;"
68-
>
69-
<div
70-
class="pf-l-stack pf-m-gutter"
71-
/>
72-
</section>
73-
</div>
7462
</div>
7563
</section>
7664
</div>
@@ -187,18 +175,6 @@ exports[`renders empty message 1`] = `
187175
</div>
188176
</div>
189177
</div>
190-
<div
191-
class="pf-l-split__item"
192-
>
193-
<section
194-
class="pf-c-page__main-section pf-m-light"
195-
style="height: 100%;"
196-
>
197-
<div
198-
class="pf-l-stack pf-m-gutter"
199-
/>
200-
</section>
201-
</div>
202178
</div>
203179
</section>
204180
</div>
@@ -266,18 +242,6 @@ exports[`renders unknown message 1`] = `
266242
</div>
267243
</div>
268244
</div>
269-
<div
270-
class="pf-l-split__item"
271-
>
272-
<section
273-
class="pf-c-page__main-section pf-m-light"
274-
style="height: 100%;"
275-
>
276-
<div
277-
class="pf-l-stack pf-m-gutter"
278-
/>
279-
</section>
280-
</div>
281245
</div>
282246
</section>
283247
</div>
@@ -442,18 +406,6 @@ exports[`renders with Global Search alert & no message 1`] = `
442406
</div>
443407
</div>
444408
</div>
445-
<div
446-
class="pf-l-split__item"
447-
>
448-
<section
449-
class="pf-c-page__main-section pf-m-light"
450-
style="height: 100%;"
451-
>
452-
<div
453-
class="pf-l-stack pf-m-gutter"
454-
/>
455-
</section>
456-
</div>
457409
</div>
458410
</section>
459411
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`renders with Global Search link 1`] = `
4+
<body>
5+
<div>
6+
<a
7+
href="/multicloud/home/search"
8+
>
9+
<button
10+
aria-disabled="false"
11+
class="pf-c-button pf-m-link pf-m-inline"
12+
data-ouia-component-id="OUIA-Generated-Button-link-2"
13+
data-ouia-component-type="PF4/Button"
14+
data-ouia-safe="true"
15+
type="button"
16+
>
17+
<span
18+
class="pf-c-button__icon pf-m-start"
19+
>
20+
<svg
21+
aria-hidden="true"
22+
fill="currentColor"
23+
height="1em"
24+
role="img"
25+
style="vertical-align: -0.125em;"
26+
viewBox="0 0 512 512"
27+
width="1em"
28+
>
29+
<path
30+
d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"
31+
/>
32+
</svg>
33+
</span>
34+
Global search
35+
</button>
36+
</a>
37+
</div>
38+
</body>
39+
`;
40+
41+
exports[`renders with default Search link 1`] = `
42+
<body>
43+
<div>
44+
<a
45+
href="/multicloud/home/search"
46+
>
47+
<button
48+
aria-disabled="false"
49+
class="pf-c-button pf-m-link pf-m-inline"
50+
data-ouia-component-id="OUIA-Generated-Button-link-1"
51+
data-ouia-component-type="PF4/Button"
52+
data-ouia-safe="true"
53+
type="button"
54+
>
55+
<span
56+
class="pf-c-button__icon pf-m-start"
57+
>
58+
<svg
59+
aria-hidden="true"
60+
fill="currentColor"
61+
height="1em"
62+
role="img"
63+
style="vertical-align: -0.125em;"
64+
viewBox="0 0 512 512"
65+
width="1em"
66+
>
67+
<path
68+
d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"
69+
/>
70+
</svg>
71+
</span>
72+
Search
73+
</button>
74+
</a>
75+
</div>
76+
</body>
77+
`;

frontend/src/ui-components/AcmPage/AcmPage.test.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ describe('AcmPageHeader', () => {
6161
expect(getByText('Create resource')).toBeInTheDocument()
6262
})
6363

64+
test('AcmPageHeader renders with search link', () => {
65+
const { getByText } = render(<AcmPageHeader breadcrumb={[]} title="ACM header" searchbar={<div>{'Search'}</div>} />)
66+
expect(getByText('Search')).toBeInTheDocument()
67+
})
68+
6469
test('AcmPageHeader has zero accessibility defects', async () => {
6570
const { container } = render(<AcmPageHeader title="ACM header" />)
6671
expect(await axe(container)).toHaveNoViolations()

frontend/src/ui-components/AcmPage/AcmPage.tsx

+32-24
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export interface AcmPageHeaderProps {
5555
controls?: React.ReactNode
5656
switches?: React.ReactNode
5757
actions?: React.ReactNode
58+
searchbar?: React.ReactNode
5859
}
5960

6061
export function AcmPageHeader(props: AcmPageHeaderProps) {
@@ -130,6 +131,11 @@ export function AcmPageHeader(props: AcmPageHeaderProps) {
130131
</SplitItem>
131132
)}
132133
{/* <SplitItem>{props.description && <p>{props.description}</p>}</SplitItem> */}
134+
{props.searchbar && (
135+
<SplitItem style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center' }}>
136+
{props.searchbar}
137+
</SplitItem>
138+
)}
133139
</Split>
134140
{props.description && <div style={{ paddingTop: '8px' }}>{props.description}</div>}
135141
</StackItem>
@@ -145,30 +151,32 @@ export function AcmPageHeader(props: AcmPageHeaderProps) {
145151
)}
146152
</Stack>
147153
</SplitItem>
148-
<SplitItem>
149-
<PageSection variant={PageSectionVariants.light} style={{ height: '100%' }}>
150-
<Stack hasGutter>
151-
{props.controls && (
152-
<StackItem style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end' }}>
153-
{props.controls}
154-
</StackItem>
155-
)}
156-
{props.actions && (
157-
<StackItem
158-
style={{
159-
display: 'flex',
160-
flexDirection: 'column',
161-
alignItems: 'flex-end',
162-
justifyContent: 'flex-end',
163-
}}
164-
isFilled
165-
>
166-
{props.actions}
167-
</StackItem>
168-
)}
169-
</Stack>
170-
</PageSection>
171-
</SplitItem>
154+
{(props.controls || props.actions) && (
155+
<SplitItem>
156+
<PageSection variant={PageSectionVariants.light} style={{ height: '100%' }}>
157+
<Stack hasGutter>
158+
{props.controls && (
159+
<StackItem style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end' }}>
160+
{props.controls}
161+
</StackItem>
162+
)}
163+
{props.actions && (
164+
<StackItem
165+
style={{
166+
display: 'flex',
167+
flexDirection: 'column',
168+
alignItems: 'flex-end',
169+
justifyContent: 'flex-end',
170+
}}
171+
isFilled
172+
>
173+
{props.actions}
174+
</StackItem>
175+
)}
176+
</Stack>
177+
</PageSection>
178+
</SplitItem>
179+
)}
172180
</Split>
173181
</PageSection>
174182
)

0 commit comments

Comments
 (0)