Skip to content

Commit ecd467c

Browse files
authored
Merge pull request #3396 from RedisInsight/fe/feature/RI-5763
#RI-5763 - add possibility for tutorials to open current page with tu…
2 parents e80426c + eedf19c commit ecd467c

File tree

27 files changed

+167
-57
lines changed

27 files changed

+167
-57
lines changed

redisinsight/ui/src/components/markdown/RedisInsightLink/RedisInsightLink.spec.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ import { render, screen, fireEvent } from 'uiSrc/utils/test-utils'
44

55
import RedisInsightLink from './RedisInsightLink'
66

7+
jest.mock('uiSrc/utils/routing', () => ({
8+
...jest.requireActual('uiSrc/utils/routing')
9+
}))
10+
11+
Object.defineProperty(window, 'location', {
12+
value: {
13+
origin: 'http://localhost'
14+
},
15+
writable: true
16+
})
17+
718
describe('RedisInsightLink', () => {
819
it('should render', () => {
920
expect(render(<RedisInsightLink url="/" text="label" />)).toBeTruthy()
@@ -13,11 +24,10 @@ describe('RedisInsightLink', () => {
1324
const pushMock = jest.fn()
1425
reactRouterDom.useHistory = jest.fn().mockReturnValue({ push: pushMock })
1526

16-
// getRedirectionPage is mocked and already has tests
17-
render(<RedisInsightLink url="/" text="label" />)
27+
render(<RedisInsightLink url="/settings" text="label" />)
1828

1929
fireEvent.click(screen.getByTestId('redisinsight-link'))
2030

21-
expect(pushMock).toHaveBeenCalledWith('/')
31+
expect(pushMock).toHaveBeenCalledWith('/settings')
2232
})
2333
})

redisinsight/ui/src/components/markdown/RedisInsightLink/RedisInsightLink.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import React, { useState } from 'react'
22
import { EuiLink, EuiPopover } from '@elastic/eui'
3-
import { useHistory, useParams } from 'react-router-dom'
3+
import { useHistory, useLocation, useParams } from 'react-router-dom'
44
import cx from 'classnames'
5+
import { isNull } from 'lodash'
56
import { getRedirectionPage } from 'uiSrc/utils/routing'
67
import DatabaseNotOpened from 'uiSrc/components/messages/database-not-opened'
78

@@ -18,22 +19,20 @@ const RedisInsightLink = (props: Props) => {
1819
const [isPopoverOpen, setIsPopoverOpen] = useState(false)
1920
const { instanceId } = useParams<{ instanceId: string }>()
2021
const history = useHistory()
22+
const location = useLocation()
2123

2224
const handleLinkClick = (e: React.MouseEvent) => {
2325
e.preventDefault()
2426

25-
if (!instanceId) {
26-
setIsPopoverOpen(true)
27-
return
28-
}
29-
30-
const href = getRedirectionPage(url, instanceId)
27+
const href = getRedirectionPage(url, instanceId, location.pathname)
3128
if (href) {
3229
history.push(href)
3330
return
3431
}
3532

36-
history.push('/')
33+
if (isNull(href)) {
34+
setIsPopoverOpen(true)
35+
}
3736
}
3837

3938
return (

redisinsight/ui/src/services/resourcesService.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ const resourcesService = axios.create({
1818
baseURL: RESOURCES_BASE_URL,
1919
})
2020

21+
// TODO: it seems it's shoudn't be location.origin
22+
// TODO: check all cases and rename this to getResourcesUrl
23+
// TODO: also might be helpful create function which returns origin url
2124
export const getOriginUrl = () => (IS_ABSOLUTE_PATH.test(RESOURCES_BASE_URL)
2225
? RESOURCES_BASE_URL
2326
: (window?.location?.origin || RESOURCES_BASE_URL))

redisinsight/ui/src/utils/routing.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { IRoute } from 'uiSrc/constants'
22
import { Maybe, Nullable } from 'uiSrc/utils'
33
import DEFAULT_ROUTES from 'uiSrc/components/main-router/constants/defaultRoutes'
44

5+
const CURRENT_PAGE_URL_SYNTAX = '/_'
6+
57
export const findRouteByPathname = (routes: IRoute[], pathname: string): Maybe<IRoute> => {
68
let findRoute
79

@@ -22,18 +24,27 @@ export const findRouteByPathname = (routes: IRoute[], pathname: string): Maybe<I
2224
return findRoute
2325
}
2426

25-
export const getRedirectionPage = (pageInput: string, databaseId?: string): Nullable<string> => {
27+
// undefined - route was not found
28+
// null - route found but private
29+
export const getRedirectionPage = (
30+
pageInput: string,
31+
databaseId?: string,
32+
currentPathname?: string
33+
): Nullable<Maybe<string>> => {
2634
let page = pageInput.replace(/^\//, '')
2735
try {
28-
const pageUrl = new URL(page, window.location.origin)
29-
const { pathname, searchParams } = pageUrl
36+
const { pathname, searchParams } = new URL(page, window.location.origin)
37+
38+
if (currentPathname && pathname === CURRENT_PAGE_URL_SYNTAX) {
39+
return `${currentPathname}?${searchParams.toString()}`
40+
}
3041

3142
if (searchParams.has('guidePath') || searchParams.has('tutorialId')) {
3243
page += '&insights=open'
3344
}
3445

3546
const foundRoute = findRouteByPathname(DEFAULT_ROUTES, pathname)
36-
if (!foundRoute) return null
47+
if (!foundRoute) return undefined
3748

3849
if (foundRoute.path.includes(':instanceId')) {
3950
if (databaseId) {
@@ -44,7 +55,7 @@ export const getRedirectionPage = (pageInput: string, databaseId?: string): Null
4455

4556
return `/${page}`
4657
} catch (_e) {
47-
return `/${page}`
58+
return undefined
4859
}
4960
}
5061

redisinsight/ui/src/utils/tests/routing.spec.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ jest.mock('uiSrc/utils/routing', () => ({
44
...jest.requireActual('uiSrc/utils/routing')
55
}))
66

7+
Object.defineProperty(window, 'location', {
8+
value: {
9+
origin: 'http://localhost'
10+
},
11+
writable: true
12+
})
13+
714
const databaseId = '1'
815
const getRedirectionPageTests = [
916
{ input: ['settings'], expected: '/settings' },
@@ -12,8 +19,12 @@ const getRedirectionPageTests = [
1219
{ input: ['/analytics/slowlog', databaseId], expected: '/1/analytics/slowlog' },
1320
{ input: ['/analytics/slowlog'], expected: null },
1421
{ input: ['/analytics', databaseId], expected: '/1/analytics' },
15-
{ input: ['/analytics/page', databaseId], expected: null },
22+
{ input: ['/analytics/page', databaseId], expected: undefined },
23+
{ input: ['/analytics'], expected: null },
24+
{ input: ['some-page'], expected: undefined },
1625
{ input: ['/workbench?guidePath=introduction.md', databaseId], expected: '/1/workbench?guidePath=introduction.md&insights=open' },
26+
{ input: ['/_?tutorialId=tutorial'], expected: undefined },
27+
{ input: ['/_?tutorialId=tutorial', databaseId, `/${databaseId}/workbench`], expected: '/1/workbench?tutorialId=tutorial' },
1728
]
1829

1930
describe('getRedirectionPage', () => {

tests/e2e/helpers/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export enum ResourcePath {
7777
}
7878

7979
export enum ExploreTabs {
80-
Explore = 'Explore',
80+
Tutorials = 'Tutorials',
8181
Tips = 'Tips',
8282
}
8383

tests/e2e/pageObjects/components/explore-tab.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export class ExploreTab {
3838
uploadDataBulkBtn = Selector('[data-testid=upload-data-bulk-btn]');
3939
uploadDataBulkApplyBtn = Selector('[data-testid=upload-data-bulk-apply-btn]');
4040
downloadFileBtn = Selector('[data-testid=download-redis-upload-file]');
41+
tutorialLink = Selector('[data-testid=redisinsight-link]');
4142

4243
//CSS
4344
cssTutorialDeleteIcon = '[data-testid^=delete-tutorial-icon-]';

tests/e2e/pageObjects/components/insights-panel.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ export class InsightsPanel {
3737
* Click on Panel tab
3838
* @param type of the tab
3939
*/
40-
async setActiveTab(type: ExploreTabs.Explore): Promise<ExploreTab>
40+
async setActiveTab(type: ExploreTabs.Tutorials): Promise<ExploreTab>
4141
async setActiveTab(type: ExploreTabs.Tips): Promise<RecommendationsTab>
4242
async setActiveTab(type: ExploreTabs): Promise<ExploreTab | RecommendationsTab> {
4343
const activeTabName = await this.getActiveTabName();
44-
if(type === ExploreTabs.Explore) {
44+
if(type === ExploreTabs.Tutorials) {
4545
if(type !== activeTabName) {
4646
await t.click(this.exploreTab);
4747
}

tests/e2e/pageObjects/memory-efficiency-page.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ export class MemoryEfficiencyPage extends InstancePage {
2121
selectedReport = Selector('[data-testid=select-report]');
2222
sortByLength = Selector('[data-testid=btn-change-table-keys]');
2323
recommendationsTab = Selector('[data-testid=Recommendations-tab]');
24+
veryUsefulVoteBtn = Selector('[data-testid=very-useful-vote-btn]').nth(0);
25+
usefulVoteBtn = Selector('[data-testid=useful-vote-btn]').nth(0);
26+
notUsefulVoteBtn = Selector('[data-testid=not-useful-vote-btn]').nth(0);
27+
recommendationsFeedbackBtn = Selector('[data-testid=recommendation-feedback-btn]');
2428
// ICONS
2529
reportTooltipIcon = Selector('[data-testid=db-new-reports-icon]');
2630
// TEXT ELEMENTS
@@ -56,10 +60,7 @@ export class MemoryEfficiencyPage extends InstancePage {
5660
readMoreLink = Selector('[data-testid=read-more-link]');
5761
workbenchLink = Selector('[data-test-subj=workbench-page-btn]');
5862
// CONTAINERS
59-
veryUsefulVoteBtn = Selector('[data-testid=very-useful-vote-btn]').nth(0);
60-
usefulVoteBtn = Selector('[data-testid=useful-vote-btn]').nth(0);
61-
notUsefulVoteBtn = Selector('[data-testid=not-useful-vote-btn]').nth(0);
62-
recommendationsFeedbackBtn = Selector('[data-testid=recommendation-feedback-btn]');
63+
analysisPage = Selector('[data-testid=database-analysis-page]');
6364

6465
/**
6566
* Get recommendation selector by name
Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,13 @@
1-
In very broad terms probabilistic data structures (PDS) allow us to get to a "close enough" result in a much shorter time and by using significantly less memory.
1+
In very broad terms probabilistic data structures (PDS) allow us to get to a "close enough" result in a much shorter time and by using significantly less memory.
2+
3+
[linkTheSamePage](redisinsight:_?tutorialId=ds-json-create)
4+
5+
[link2AnalyticsPageWithTutorial](redisinsight:analytics/database-analysis?tutorialId=ds-json-intro)
6+
7+
[link3InvalidPage](redisinsight:invalidPage?tutorialId=ds-json-intro)
8+
9+
[link4InvalidTutorial](redisinsight:invalidPage?tutorialId=invalid-tutorial)
10+
11+
[link5JustAnalyticsPage](redisinsight:analytics/database-analysis)
12+
13+
[link6JustTheSamePage](redisinsight:_)

0 commit comments

Comments
 (0)