Skip to content

Commit d4d722d

Browse files
committed
Basic guide resolving done
1 parent 3bf3508 commit d4d722d

File tree

11 files changed

+259
-53
lines changed

11 files changed

+259
-53
lines changed

src/browser/modules/Sidebar/GuideDrawer.tsx renamed to src/browser/modules/Sidebar/GuidesDrawer.tsx

Lines changed: 21 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,17 @@
2121
import React, { useEffect, useState } from 'react'
2222
import { Drawer, DrawerBody, DrawerHeader } from 'browser-components/drawer'
2323
import styled from 'styled-components'
24-
import { GuideChapter, isGuideChapter } from 'browser/documentation'
25-
import docs from '../../documentation'
26-
import Docs from '../Docs/Docs'
24+
import Directives from 'browser-components/Directives'
25+
import { CarouselButton } from 'browser-components/buttons'
26+
import {
27+
SlidePreviousIcon,
28+
SlideNextIcon
29+
} from 'browser-components/icons/Icons'
30+
import { useRef } from 'react'
31+
import { connect } from 'react-redux'
32+
import { getGuide } from 'shared/modules/guides/guidesDuck'
33+
import { GlobalState } from 'shared/globalState'
34+
import { Guide } from '../../../shared/modules/guides/guidesDuck'
2735

2836
const StyledCarousel = styled.div`
2937
padding-bottom: 20px;
@@ -162,65 +170,34 @@ const StyledUl = styled.ul`
162170
const WideDrawer = styled(Drawer)`
163171
width: 500px;
164172
position: relative;
165-
background-color: ${props => props.theme.primaryBackground};
173+
background-color: ${props => props.theme.secondaryBackground};
166174
`
167175

168-
const sidebarGuides: GuideChapter[] = [
169-
'allGuides',
170-
'intro',
171-
'concepts',
172-
'cypher',
173-
'movies',
174-
'northwind'
175-
]
176-
177176
const GuideContent = styled.div`
178177
padding-bottom: 40px;
179178
`
179+
const defaultGuide: Guide = { guideName: 'intro', initialSlide: 0, slides: [] }
180180

181-
function GuideDrawer(): JSX.Element {
182-
const [selectedGuide, setSelectedGuide] = useState<GuideChapter>('allGuides')
183-
function onSelectChange(e: React.FormEvent<HTMLSelectElement>) {
184-
e.preventDefault()
185-
if (!isGuideChapter(e.currentTarget.value)) {
186-
throw Error('invalid select target')
187-
}
188-
setSelectedGuide(e.currentTarget.value)
189-
}
190-
181+
type GuideDrawerProps = { guide: Guide | null }
182+
// default är switchern
183+
function GuideDrawer({ guide }: GuideDrawerProps): JSX.Element {
184+
const guideOrDefault = guide ?? defaultGuide
191185
return (
192186
<WideDrawer id="guide-drawer">
193187
<DrawerHeader>Neo4j Browser Guides</DrawerHeader>
194188
<DrawerBody>
195-
<select
196-
style={{ color: 'black' }}
197-
value={selectedGuide}
198-
onChange={onSelectChange}
199-
>
200-
{sidebarGuides.map(guideName => (
201-
<option key={guideName} value={guideName}>
202-
{guideName}
203-
</option>
204-
))}
205-
</select>
206189
<GuideContent>
207-
<Carousel slides={docs.play.chapters[selectedGuide].slides} />
190+
<Carousel slides={guideOrDefault.slides} />
208191
</GuideContent>
209192
</DrawerBody>
210193
</WideDrawer>
211194
)
212195
}
213-
export default GuideDrawer
214-
215-
import Directives from 'browser-components/Directives'
216-
import { CarouselButton } from 'browser-components/buttons'
217-
import {
218-
SlidePreviousIcon,
219-
SlideNextIcon
220-
} from 'browser-components/icons/Icons'
221-
import { useRef } from 'react'
196+
const mapStateToProps = (state: GlobalState) => ({ guide: getGuide(state) })
197+
export default connect(mapStateToProps)(GuideDrawer)
222198

223199
type CarouselProps = { slides?: JSX.Element[]; initialSlide?: number }
200+
// TODO handle there only being one slide
224201
function Carousel({
225202
slides = [],
226203
initialSlide = 0

src/browser/modules/Sidebar/Sidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import DatabaseDrawer from '../DBMSInfo/DBMSInfo'
2424
import DocumentsDrawer from './Documents'
2525
import AboutDrawer from './About'
2626
import SettingsDrawer from './Settings'
27-
import GuideDrawer from './GuideDrawer'
27+
import GuideDrawer from './GuidesDrawer'
2828
import Favorites from './favorites'
2929
import StaticScripts from './static-scripts'
3030
import ProjectFilesDrawer from './ProjectFiles'

src/shared/globalState.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import { NAME as folders, Folder } from './modules/favorites/foldersDuck'
5757
import { NAME as commands } from './modules/commands/commandsDuck'
5858
import { NAME as udc, udcState } from './modules/udc/udcDuck'
5959
import { NAME as app } from './modules/app/appDuck'
60+
import { NAME as guides, GuideState } from './modules/guides/guidesDuck'
6061
import {
6162
NAME as experimentalFeatures,
6263
initialState as experimentalFeaturesInitialState
@@ -83,4 +84,5 @@ export interface GlobalState {
8384
[udc]: udcState
8485
[app]: Record<string, unknown>
8586
[experimentalFeatures]: typeof experimentalFeaturesInitialState
87+
[guides]: GuideState
8688
}

src/shared/modules/commands/helpers/play.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { cleanHtml } from 'services/remoteUtils'
2323
import remote from 'services/remote'
2424

2525
export const fetchRemoteGuide = (url: any, allowlist = null) => {
26-
return new Promise((resolve, reject) => {
26+
return new Promise<void>((resolve, reject) => {
2727
if (!hostIsAllowed(url, allowlist)) {
2828
return reject(
2929
new Error('Hostname is not allowed according to server allowlist')
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Neo4j is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
import { GlobalState } from 'shared/globalState'
22+
23+
export const NAME = 'guides'
24+
export const START_GUIDE = 'sidebar/START_GUIDE'
25+
26+
export const getGuide = (state: GlobalState): Guide | null => state[NAME].guide
27+
// Todo the refactor I want is for this to include
28+
// everything needed to show the guide not this
29+
// half measure
30+
export type Guide = {
31+
initialSlide: number
32+
guideName: string
33+
slides: JSX.Element[]
34+
}
35+
36+
export interface GuideState {
37+
guide: Guide | null
38+
}
39+
const initialState: GuideState = {
40+
guide: null
41+
}
42+
43+
type GuideAction = StartAction
44+
45+
interface StartAction {
46+
type: typeof START_GUIDE
47+
guide: Guide
48+
}
49+
50+
export default function reducer(
51+
state = initialState,
52+
action: GuideAction
53+
): GuideState {
54+
switch (action.type) {
55+
case START_GUIDE:
56+
return { ...state, guide: action.guide }
57+
default:
58+
return state
59+
}
60+
}
61+
62+
export function startGuide(guide: Guide): StartAction {
63+
return { type: START_GUIDE, guide }
64+
}

src/shared/modules/history/historyDuck.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ describe('editor reducer', () => {
3535
// Given
3636
const helpAction = actions.addHistory(':help', 20)
3737
const historyAction = actions.addHistory(':history', 20)
38-
const initalState = [':help']
38+
const initialState = [':help']
3939

4040
// When
41-
const nextState = reducer(initalState, helpAction)
41+
const nextState = reducer(initialState, helpAction)
4242

4343
// Then
4444
expect(nextState).toEqual([':help'])
@@ -51,18 +51,18 @@ describe('editor reducer', () => {
5151
})
5252

5353
test('takes editor.actionTypes.SET_MAX_HISTORY into account', () => {
54-
const initalState = [':help', ':help', ':help']
54+
const initialState = [':help', ':help', ':help']
5555

5656
const helpAction = actions.addHistory(':history', 3)
57-
const nextState = reducer(initalState, helpAction)
57+
const nextState = reducer(initialState, helpAction)
5858
expect(nextState).toEqual([':history', ':help', ':help'])
5959
})
6060

6161
test('handles editor.actionTypes.CLEAR_HISTORY', () => {
6262
// Given
63-
const initalState = [':emily']
63+
const initialState = [':emily']
6464
const anAction = actions.addHistory(':elliot', 3)
65-
const state = reducer(initalState, anAction)
65+
const state = reducer(initialState, anAction)
6666

6767
// When
6868
const nextState = reducer(state, actions.clearHistory())

src/shared/modules/sidebar/sidebarDuck.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ type DrawerId =
4848
| 'documents'
4949
| 'sync'
5050
| 'favorites'
51+
| 'guides'
5152
| 'about'
5253
| 'project files'
5354
| 'settings'

src/shared/rootReducer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import commandsReducer, {
6262
} from 'shared/modules/commands/commandsDuck'
6363
import udcReducer, { NAME as udc } from 'shared/modules/udc/udcDuck'
6464
import appReducer, { NAME as app } from 'shared/modules/app/appDuck'
65+
import guideReducer, { NAME as guides } from 'shared/modules/guides/guidesDuck'
6566
import experimentalFeaturesReducer, {
6667
NAME as experimentalFeatures
6768
} from 'shared/modules/experimentalFeatures/experimentalFeaturesDuck'
@@ -86,5 +87,6 @@ export default {
8687
[commands]: commandsReducer,
8788
[udc]: udcReducer,
8889
[app]: appReducer,
90+
[guides]: guideReducer,
8991
[experimentalFeatures]: experimentalFeaturesReducer
9092
}

src/shared/services/commandInterpreterHelper.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ import {
3535
useDb,
3636
getUseDb
3737
} from 'shared/modules/connections/connectionsDuck'
38+
import { open } from 'shared/modules/sidebar/sidebarDuck'
39+
import { startGuide } from 'shared/modules/guides/guidesDuck'
3840
import { getParams } from 'shared/modules/params/paramsDuck'
3941
import { getUserCapabilities } from 'shared/modules/features/featuresDuck'
4042
import {
@@ -99,6 +101,7 @@ import {
99101
} from './commandUtils'
100102
import { unescapeCypherIdentifier } from './utils'
101103
import { getLatestFromFrameStack } from 'browser/modules/Stream/stream.utils'
104+
import { resolveGuide } from './guideResolverHelper'
102105

103106
const PLAY_FRAME_TYPES = ['play', 'play-remote']
104107

@@ -467,6 +470,25 @@ const availableCommands = [
467470
}
468471
}
469472
},
473+
{
474+
name: 'guide',
475+
match: (cmd: any) => /^guide(\s|$)/.test(cmd),
476+
exec(action: any, put: any, store: any) {
477+
const guideName = action.cmd.substr(':guide'.length).trim()
478+
const initialSlide = tryGetRemoteInitialSlideFromUrl(action.cmd)
479+
resolveGuide(guideName, store).then(({ slides }) => {
480+
put(
481+
startGuide({
482+
initialSlide,
483+
guideName,
484+
slides
485+
})
486+
)
487+
488+
put(open('guides'))
489+
})
490+
}
491+
},
470492
{
471493
name: 'play-remote',
472494
match: (cmd: any) => /^play(\s|$)https?/.test(cmd),

0 commit comments

Comments
 (0)