Skip to content

Commit 02f6f9d

Browse files
committed
#RI-4877 - create a free cloud db from tutorials
1 parent e70d745 commit 02f6f9d

File tree

10 files changed

+127
-2
lines changed

10 files changed

+127
-2
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React from 'react'
2+
import { render, screen } from 'uiSrc/utils/test-utils'
3+
4+
import CloudLink from './CloudLink'
5+
6+
describe('CloudLink', () => {
7+
it('should render', () => {
8+
expect(render(<CloudLink text="Link" url="" />)).toBeTruthy()
9+
})
10+
11+
it('should render proper url', () => {
12+
const url = 'https://site.com'
13+
render(<CloudLink text="Link" url={url} />)
14+
15+
expect(screen.getByTestId('guide-free-database-link').getAttribute('href')).toBe(url)
16+
})
17+
})
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from 'react'
2+
import { EuiLink } from '@elastic/eui'
3+
import { OAuthSocialSource } from 'uiSrc/slices/interfaces'
4+
import { OAuthSsoHandlerDialog } from 'uiSrc/components'
5+
6+
export interface Props {
7+
url: string
8+
text: string
9+
}
10+
11+
const CloudLink = (props: Props) => {
12+
const { url, text } = props
13+
return (
14+
<OAuthSsoHandlerDialog>
15+
{(ssoCloudHandlerClick) => (
16+
<EuiLink
17+
color="text"
18+
onClick={(e) => {
19+
ssoCloudHandlerClick(e, OAuthSocialSource.Tutorials)
20+
}}
21+
external={false}
22+
target="_blank"
23+
href={url}
24+
data-testid="guide-free-database-link"
25+
>
26+
{text}
27+
</EuiLink>
28+
)}
29+
</OAuthSsoHandlerDialog>
30+
)
31+
}
32+
33+
export default CloudLink
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import CloudLink from './CloudLink'
2+
3+
export default CloudLink

redisinsight/ui/src/pages/workbench/components/enablement-area/EnablementArea/components/InternalPage/InternalPage.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
Code,
1818
EmptyPrompt,
1919
RedisUploadButton,
20+
CloudLink,
2021
Pagination
2122
} from 'uiSrc/pages/workbench/components/enablement-area/EnablementArea/components'
2223
import { getTutorialSection } from 'uiSrc/pages/workbench/components/enablement-area/EnablementArea/utils'
@@ -59,7 +60,7 @@ const InternalPage = (props: Props) => {
5960
manifestPath,
6061
sourcePath
6162
} = props
62-
const components: any = { LazyCodeButton, Image, Code, RedisUploadButton }
63+
const components: any = { LazyCodeButton, Image, Code, RedisUploadButton, CloudLink }
6364
const containerRef = useRef<HTMLDivElement>(null)
6465
const { instanceId = '' } = useParams<{ instanceId: string }>()
6566
const handleScroll = debounce(() => {

redisinsight/ui/src/pages/workbench/components/enablement-area/EnablementArea/components/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Pagination from './Pagination'
1212
import UploadTutorialForm from './UploadTutorialForm'
1313
import WelcomeMyTutorials from './WelcomeMyTutorials'
1414
import RedisUploadButton from './RedisUploadButton'
15+
import CloudLink from './CloudLink'
1516

1617
export {
1718
Code,
@@ -28,4 +29,5 @@ export {
2829
UploadTutorialForm,
2930
WelcomeMyTutorials,
3031
RedisUploadButton,
32+
CloudLink,
3133
}

redisinsight/ui/src/pages/workbench/components/enablement-area/EnablementArea/utils/formatter/MarkdownToJsxString.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { rehypeLinks } from '../transform/rehypeLinks'
1010
import { remarkRedisUpload } from '../transform/remarkRedisUpload'
1111
import { remarkRedisCode } from '../transform/remarkRedisCode'
1212
import { remarkImage } from '../transform/remarkImage'
13+
import { remarkLink } from '../transform/remarkLink'
1314

1415
class MarkdownToJsxString implements IFormatter {
1516
format(input: any, config?: IFormatterConfig): Promise<string> {
@@ -21,6 +22,7 @@ class MarkdownToJsxString implements IFormatter {
2122
.use(remarkRedisUpload, path) // Add custom component for redis-upload code block
2223
.use(remarkRedisCode) // Add custom component for Redis code block
2324
.use(remarkImage, path) // Add custom component for Redis code block
25+
.use(remarkLink) // Add custom component for Redis code block
2426
.use(remarkRehype, { allowDangerousHtml: true }) // Pass raw HTML strings through.
2527
.use(rehypeLinks, config ? { history: config.history } : undefined) // Customise links
2628
.use(MarkdownToJsxString.rehypeWrapSymbols) // Wrap special symbols inside curly braces for JSX parse
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { visit } from 'unist-util-visit'
2+
import { remarkLink } from '../transform/remarkLink'
3+
4+
jest.mock('unist-util-visit')
5+
6+
describe('remarkLink', () => {
7+
it('should not modify codeNode if title is not Redis Cloud', () => {
8+
const codeNode = {
9+
type: 'link',
10+
url: 'https://mysite.com',
11+
children: [
12+
{
13+
type: 'text',
14+
value: 'Redis Stack Server'
15+
}
16+
]
17+
};
18+
// mock implementation
19+
(visit as jest.Mock)
20+
.mockImplementation((_tree: any, _name: string, callback: (codeNode: any) => void) => { callback(codeNode) })
21+
22+
const remark = remarkLink()
23+
remark({} as Node)
24+
expect(codeNode).toEqual({
25+
...codeNode
26+
})
27+
})
28+
29+
it('should properly modify codeNode with title Redis Cloud', () => {
30+
const codeNode = {
31+
title: 'Redis Cloud',
32+
type: 'link',
33+
url: 'https://mysite.com',
34+
children: [
35+
{
36+
type: 'text',
37+
value: 'Setup Redis Cloud'
38+
}
39+
]
40+
};
41+
// mock implementation
42+
(visit as jest.Mock)
43+
.mockImplementation((_tree: any, _name: string, callback: (codeNode: any) => void) => { callback(codeNode) })
44+
45+
const remark = remarkLink()
46+
remark({} as Node)
47+
expect(codeNode).toEqual({
48+
...codeNode,
49+
type: 'html',
50+
value: '<CloudLink url="https://mysite.com" text="Setup Redis Cloud" />',
51+
})
52+
})
53+
})

redisinsight/ui/src/pages/workbench/components/enablement-area/EnablementArea/utils/transform/rehypeLinks.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { visit } from 'unist-util-visit'
2-
import { IS_ABSOLUTE_PATH } from 'uiSrc/constants/regex'
32
import { createLocation, History } from 'history'
3+
import { IS_ABSOLUTE_PATH } from 'uiSrc/constants/regex'
44

55
interface IConfig {
66
history: History
@@ -13,6 +13,7 @@ export const rehypeLinks = (config?: IConfig): (tree: Node) => void => (tree: an
1313
if (IS_ABSOLUTE_PATH.test(url)) { // External link
1414
node.properties.rel = ['nofollow', 'noopener', 'noreferrer']
1515
node.properties.target = '_blank'
16+
// delete node.properties.title
1617
}
1718
if (url.startsWith('#') && config?.history) {
1819
const { location: currentLocation } = config.history
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { visit } from 'unist-util-visit'
2+
3+
export const remarkLink = (): (tree: Node) => void => (tree: any) => {
4+
// Find link node in syntax tree
5+
visit(tree, 'link', (node) => {
6+
if (node.title === 'Redis Cloud') {
7+
const [text] = node.children || []
8+
node.type = 'html'
9+
node.value = `<CloudLink url="${node.url}" text="${text?.value || 'Redis Cloud'}" />`
10+
}
11+
})
12+
}

redisinsight/ui/src/slices/interfaces/cloud.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,5 @@ export enum OAuthSocialSource {
7272
ConfirmationMessage = 'confirmation message',
7373
TriggersAndFunctions = 'triggers_and_functions',
7474
'triggers and functions' = 'workbench triggers_and_functions',
75+
Tutorials = 'tutorials'
7576
}

0 commit comments

Comments
 (0)