Skip to content

Commit dbbe0e6

Browse files
authored
Merge pull request #2893 from RedisInsight/fe/feature/RI-5246-insights-opening
#RI-5246 - cover open tutorial buttons
2 parents 8fca6d0 + 5565686 commit dbbe0e6

File tree

21 files changed

+148
-97
lines changed

21 files changed

+148
-97
lines changed

redisinsight/api/src/__mocks__/custom-tutorial.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export const mockCustomTutorialManifestJson = {
7474
type: CustomTutorialManifestType.InternalLink,
7575
id: 'introduction',
7676
label: 'introduction',
77+
summary: 'Introduction summary',
7778
args: {
7879
path: '/ct-folder-1/ct-sub-folder-1/introduction.md',
7980
},

redisinsight/api/src/modules/custom-tutorial/models/custom-tutorial.manifest.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ export class CustomTutorialManifest {
6262
@IsNotEmpty()
6363
label: string;
6464

65+
@ApiProperty({ type: String })
66+
@IsOptional()
67+
@Expose()
68+
@IsString()
69+
@IsNotEmpty()
70+
summary?: string;
71+
6572
@ApiPropertyOptional({ type: CustomTutorialManifestArgs })
6673
@IsOptional()
6774
@Expose()

redisinsight/ui/src/components/database-side-panels/panels/enablement-area/EnablementArea/EnablementArea.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,12 @@ const EnablementArea = (props: Props) => {
9797
}, [search, tutorials, guides])
9898

9999
useEffect(() => {
100-
const manifestPath = new URLSearchParams(search).get('path')
101-
const guidePath = new URLSearchParams(search).get('guidePath')
102-
const contextManifestPath = new URLSearchParams(searchEAContext).get('path')
100+
const searchParams = new URLSearchParams(search)
101+
const searchContextParams = new URLSearchParams(searchEAContext)
102+
103+
const manifestPath = searchParams.get('path')
104+
const guidePath = searchParams.get('guidePath')
105+
const contextManifestPath = searchContextParams.get('path')
103106
const { manifest, prefixFolder } = getManifestByPath(manifestPath)
104107

105108
if (guidePath || (isEmpty(manifest) && !contextManifestPath)) {

redisinsight/ui/src/components/database-side-panels/panels/live-time-recommendations/LiveTimeRecommendations.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useEffect, useState } from 'react'
22
import { useDispatch, useSelector } from 'react-redux'
3-
import { useHistory } from 'react-router-dom'
3+
import { useHistory, useParams } from 'react-router-dom'
44
import {
55
EuiLink,
66
EuiLoadingContent,
@@ -37,7 +37,7 @@ import PopoverRunAnalyze from './components/popover-run-analyze'
3737
import styles from './styles.module.scss'
3838

3939
const LiveTimeRecommendations = () => {
40-
const { id: connectedInstanceId = '', provider, connectionType } = useSelector(connectedInstanceSelector)
40+
const { provider, connectionType } = useSelector(connectedInstanceSelector)
4141
const {
4242
loading,
4343
data: { recommendations },
@@ -48,6 +48,8 @@ const LiveTimeRecommendations = () => {
4848
treeViewDelimiter: delimiter = '',
4949
} = useSelector(appContextDbConfig)
5050

51+
const { instanceId } = useParams<{ instanceId: string }>()
52+
5153
const [isShowApproveRun, setIsShowApproveRun] = useState<boolean>(false)
5254

5355
const dispatch = useDispatch()
@@ -56,20 +58,20 @@ const LiveTimeRecommendations = () => {
5658
const isShowHiddenDisplayed = recommendations.filter((r) => r.hide).length > 0
5759

5860
useEffect(() => {
59-
dispatch(fetchRecommendationsAction(connectedInstanceId))
61+
dispatch(fetchRecommendationsAction(instanceId))
6062

6163
return () => {
62-
dispatch(readRecommendationsAction(connectedInstanceId))
64+
dispatch(readRecommendationsAction(instanceId))
6365
}
6466
}, [])
6567

6668
const handleClickDbAnalysisLink = () => {
67-
dispatch(createNewAnalysis(connectedInstanceId, delimiter))
68-
history.push(Pages.databaseAnalysis(connectedInstanceId))
69+
dispatch(createNewAnalysis(instanceId, delimiter))
70+
history.push(Pages.databaseAnalysis(instanceId))
6971
sendEventTelemetry({
7072
event: TelemetryEvent.INSIGHTS_RECOMMENDATION_DATABASE_ANALYSIS_CLICKED,
7173
eventData: {
72-
databaseId: connectedInstanceId,
74+
databaseId: instanceId,
7375
total: recommendations?.length,
7476
provider
7577
},
@@ -90,7 +92,7 @@ const LiveTimeRecommendations = () => {
9092
}
9193

9294
const getTelemetryData = (recommendationsData: IRecommendation[]) => ({
93-
databaseId: connectedInstanceId,
95+
databaseId: instanceId,
9496
total: recommendationsData?.length,
9597
list: recommendationsData?.map(({ name }) => recommendationsContent[name]?.telemetryEvent ?? name),
9698
provider

redisinsight/ui/src/components/database-side-panels/panels/live-time-recommendations/components/recommendation/Recommendation.spec.tsx

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ import reactRouterDom from 'react-router-dom'
44
import { cloneDeep } from 'lodash'
55
import { fireEvent, screen, render, mockedStore, cleanup, act } from 'uiSrc/utils/test-utils'
66
import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry'
7-
import { Pages } from 'uiSrc/constants'
87

98
import { updateRecommendation } from 'uiSrc/slices/recommendations/recommendations'
109
import { INSTANCE_ID_MOCK } from 'uiSrc/mocks/handlers/instances/instancesHandlers'
1110
import { MOCK_RECOMMENDATIONS } from 'uiSrc/constants/mocks/mock-recommendations'
12-
import { openNewWindowDatabase } from 'uiSrc/utils'
1311
import Recommendation, { IProps } from './Recommendation'
1412

1513
const recommendationsContent = MOCK_RECOMMENDATIONS
@@ -25,11 +23,6 @@ jest.mock('uiSrc/telemetry', () => ({
2523
sendEventTelemetry: jest.fn(),
2624
}))
2725

28-
jest.mock('uiSrc/utils', () => ({
29-
...jest.requireActual('uiSrc/utils'),
30-
openNewWindowDatabase: jest.fn(),
31-
}))
32-
3326
let store: typeof mockedStore
3427
beforeEach(() => {
3528
cleanup()
@@ -82,7 +75,7 @@ describe('Recommendation', () => {
8275
fireEvent.click(container.querySelector('[data-test-subj="searchJSON-button"]') as HTMLButtonElement)
8376
fireEvent.click(screen.getByTestId('searchJSON-to-tutorial-btn'))
8477

85-
expect(pushMock).toHaveBeenCalledWith(Pages.workbench(INSTANCE_ID_MOCK))
78+
expect(pushMock).toHaveBeenCalledWith({ search: 'guidePath=' })
8679
expect(sendEventTelemetry).toBeCalledWith({
8780
event: TelemetryEvent.INSIGHTS_RECOMMENDATION_TUTORIAL_CLICKED,
8881
eventData: {
@@ -96,8 +89,8 @@ describe('Recommendation', () => {
9689

9790
it('should properly call openNewWindowDatabase and open a new window on workbench page to specific guide', () => {
9891
// will be improved
99-
const openNewWindowDatabaseMock = jest.fn();
100-
(openNewWindowDatabase as jest.Mock).mockImplementation(() => openNewWindowDatabaseMock)
92+
const pushMock = jest.fn()
93+
reactRouterDom.useHistory = jest.fn().mockReturnValue({ push: pushMock })
10194

10295
const { container } = render(
10396
<Recommendation
@@ -112,8 +105,10 @@ describe('Recommendation', () => {
112105
fireEvent.click(container.querySelector('[data-test-subj="searchJSON-button"]') as HTMLButtonElement)
113106
fireEvent.click(screen.getByTestId('searchJSON-to-tutorial-btn'))
114107

115-
expect(openNewWindowDatabase)
116-
.toHaveBeenCalledWith(`${Pages.workbench(INSTANCE_ID_MOCK)}?guidePath=quick-guides/working-with-hash.html`)
108+
expect(pushMock)
109+
.toHaveBeenCalledWith({
110+
search: 'guidePath=quick-guides/working-with-hash.html'
111+
})
117112
expect(sendEventTelemetry).toBeCalledWith({
118113
event: TelemetryEvent.INSIGHTS_RECOMMENDATION_TUTORIAL_CLICKED,
119114
eventData: {
@@ -123,13 +118,13 @@ describe('Recommendation', () => {
123118
}
124119
})
125120
sendEventTelemetry.mockRestore()
126-
openNewWindowDatabase.mockRestore()
121+
pushMock.mockRestore()
127122
})
128123

129124
it('should properly push history on workbench page to specific tutorial', () => {
130125
// will be improved
131-
const openNewWindowDatabaseMock = jest.fn();
132-
(openNewWindowDatabase as jest.Mock).mockImplementation(() => openNewWindowDatabaseMock)
126+
const pushMock = jest.fn()
127+
reactRouterDom.useHistory = jest.fn().mockReturnValue({ push: pushMock })
133128

134129
const { container } = render(
135130
<Recommendation
@@ -144,8 +139,10 @@ describe('Recommendation', () => {
144139
fireEvent.click(container.querySelector('[data-test-subj="searchJSON-button"]') as HTMLButtonElement)
145140
fireEvent.click(screen.getByTestId('searchJSON-to-tutorial-btn'))
146141

147-
expect(openNewWindowDatabase)
148-
.toHaveBeenCalledWith(`${Pages.workbench(INSTANCE_ID_MOCK)}?guidePath=/redis_stack/working_with_json.md`)
142+
expect(pushMock)
143+
.toHaveBeenCalledWith({
144+
search: 'guidePath=/redis_stack/working_with_json.md'
145+
})
149146
expect(sendEventTelemetry).toBeCalledWith({
150147
event: TelemetryEvent.INSIGHTS_RECOMMENDATION_TUTORIAL_CLICKED,
151148
eventData: {
@@ -155,7 +152,7 @@ describe('Recommendation', () => {
155152
}
156153
})
157154
sendEventTelemetry.mockRestore()
158-
openNewWindowDatabase.mockRestore()
155+
pushMock.mockRestore()
159156
})
160157

161158
it('should render hide/unhide button', () => {

redisinsight/ui/src/components/database-side-panels/panels/live-time-recommendations/components/recommendation/Recommendation.tsx

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ import {
1616
import { isUndefined } from 'lodash'
1717
import cx from 'classnames'
1818

19-
import { Nullable, Maybe, openNewWindowDatabase } from 'uiSrc/utils'
19+
import { Nullable, Maybe } from 'uiSrc/utils'
2020
import { renderRecommendationContent } from 'uiSrc/utils/recommendation/utils'
21-
import { Pages, Theme } from 'uiSrc/constants'
21+
import { Theme } from 'uiSrc/constants'
2222
import { RecommendationVoting, RecommendationCopyComponent } from 'uiSrc/components'
2323
import { Vote } from 'uiSrc/constants/recommendations'
2424
import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry'
@@ -32,6 +32,7 @@ import RediStackLightMin from 'uiSrc/assets/img/modules/redistack/RediStackLight
3232
import { ReactComponent as SnoozeIcon } from 'uiSrc/assets/img/icons/snooze.svg'
3333
import { ReactComponent as StarsIcon } from 'uiSrc/assets/img/icons/stars.svg'
3434

35+
import { openTutorialByPath } from 'uiSrc/slices/panels/insights'
3536
import styles from './styles.module.scss'
3637

3738
export interface IProps {
@@ -77,14 +78,7 @@ const Recommendation = ({
7778
}
7879
})
7980

80-
// dispatch(setWorkbenchEAOpened(false))
81-
if (tutorial) {
82-
openNewWindowDatabase(`${Pages.workbench(instanceId)}?guidePath=${tutorial}`)
83-
return
84-
}
85-
86-
// dispatch(resetExplorePanelSearchContext())
87-
history.push(Pages.workbench(instanceId))
81+
dispatch(openTutorialByPath(tutorial || '', history))
8882
}
8983

9084
const toggleHide = (event: React.MouseEvent) => {

redisinsight/ui/src/components/explore-guides/ExploreGuides.spec.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ describe('ExploreGuides', () => {
5252
fireEvent.click(screen.getByTestId('guide-button-Search and Query'))
5353

5454
expect(pushMock)
55-
.toHaveBeenCalledWith(`${Pages.workbench(INSTANCE_ID_MOCK)}?guidePath=/quick-guides/document/introduction.md`)
55+
.toHaveBeenCalledWith({
56+
search: 'guidePath=/quick-guides/document/introduction.md'
57+
})
5658
})
5759

5860
it('should call proper history push after click on guide with tutorial', () => {
@@ -63,9 +65,9 @@ describe('ExploreGuides', () => {
6365

6466
fireEvent.click(screen.getByTestId('guide-button-JSON'))
6567

66-
expect(pushMock).toHaveBeenCalledWith(
67-
`${Pages.workbench(INSTANCE_ID_MOCK)}?guidePath=/quick-guides/document/working-with-json.md`
68-
)
68+
expect(pushMock).toHaveBeenCalledWith({
69+
search: 'guidePath=/quick-guides/document/working-with-json.md'
70+
})
6971
})
7072

7173
it('should call proper telemetry event after click on guide', () => {

redisinsight/ui/src/components/explore-guides/ExploreGuides.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import { EuiIcon, EuiText, EuiTitle, EuiSpacer } from '@elastic/eui'
33
import { useDispatch, useSelector } from 'react-redux'
44
import { useHistory, useParams } from 'react-router-dom'
55
import { guideLinksSelector } from 'uiSrc/slices/content/guide-links'
6-
import { Pages } from 'uiSrc/constants'
76

87
import GUIDE_ICONS from 'uiSrc/components/explore-guides/icons'
98
import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry'
109
import { connectedInstanceSelector } from 'uiSrc/slices/instances/instances'
1110
import { keysSelector } from 'uiSrc/slices/browser/keys'
1211

12+
import { openTutorialByPath } from 'uiSrc/slices/panels/insights'
1313
import styles from './styles.module.scss'
1414

1515
const ExploreGuides = () => {
@@ -23,8 +23,6 @@ const ExploreGuides = () => {
2323
const dispatch = useDispatch()
2424

2525
const handleLinkClick = (tutorial: string, title: string) => {
26-
// dispatch(setWorkbenchEAOpened(false))
27-
2826
sendEventTelemetry({
2927
event: TelemetryEvent.BROWSER_TUTORIAL_CLICKED,
3028
eventData: {
@@ -35,14 +33,7 @@ const ExploreGuides = () => {
3533
}
3634
})
3735

38-
// dispatch(setWorkbenchEAOpened(false))
39-
if (tutorial) {
40-
history.push(`${Pages.workbench(instanceId)}?guidePath=${tutorial}`)
41-
return
42-
}
43-
44-
// dispatch(resetExplorePanelSearchContext())
45-
history.push(Pages.workbench(instanceId))
36+
dispatch(openTutorialByPath(tutorial, history))
4637
}
4738

4839
return (

redisinsight/ui/src/components/insights-trigger/InsightsTrigger.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import React, { useEffect } from 'react'
22
import cx from 'classnames'
33
import { EuiButton, EuiText, EuiToolTip } from '@elastic/eui'
44

@@ -20,13 +20,23 @@ const InsightsTrigger = () => {
2020
const { provider } = useSelector(connectedInstanceSelector)
2121

2222
const dispatch = useDispatch()
23-
const { pathname } = useLocation()
23+
const { pathname, search } = useLocation()
2424
const { instanceId } = useParams<{ instanceId: string }>()
2525

2626
const page = pathname
2727
.replace(instanceId, '')
2828
.replace(/^\//g, '')
2929

30+
useEffect(() => {
31+
const searchParams = new URLSearchParams(search)
32+
const isExploreShouldBeOpened = searchParams.get('insights') === 'open'
33+
34+
if (isExploreShouldBeOpened) {
35+
dispatch(toggleInsightsPanel(true))
36+
dispatch(changeSelectedTab(InsightsPanelTabs.Explore))
37+
}
38+
}, [search])
39+
3040
const handleClickTrigger = () => {
3141
if (isHighlighted) {
3242
dispatch(resetRecommendationsHighlighting())

redisinsight/ui/src/constants/storage.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ enum BrowserStorageItem {
2929
showHiddenRecommendations = 'showHiddenRecommendations',
3030
OAuthJobId = 'OAuthJobId',
3131
OAuthAgreement = 'OAuthAgreement',
32-
capability = 'capability'
32+
insightsPanel = 'insightsPanel',
33+
capability = 'capability',
3334
}
3435

3536
export default BrowserStorageItem

0 commit comments

Comments
 (0)