From 531c2490cd38c9fcbe047240e3a0a9a6b8a07315 Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Wed, 5 May 2021 11:03:50 +0200 Subject: [PATCH 01/16] Avoid extra new lines for in

in

  • --- src/browser/documentation/sidebar-guides/movie-graph.tsx | 1 - src/browser/documentation/sidebar-guides/styled.tsx | 4 +--- src/browser/modules/Carousel/styled.tsx | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/browser/documentation/sidebar-guides/movie-graph.tsx b/src/browser/documentation/sidebar-guides/movie-graph.tsx index 02f961d8f97..beb664a6098 100644 --- a/src/browser/documentation/sidebar-guides/movie-graph.tsx +++ b/src/browser/documentation/sidebar-guides/movie-graph.tsx @@ -21,7 +21,6 @@ import React from 'react' import ManualLink from 'browser-components/ManualLink' import { SidebarSlide } from '../../modules/Carousel/Slide' -import { BulletsInsideLi } from './styled' import { DrawerExternalLink } from 'browser-components/drawer/drawer-styled' const title = 'Movie Graph' diff --git a/src/browser/documentation/sidebar-guides/styled.tsx b/src/browser/documentation/sidebar-guides/styled.tsx index 19015856d08..45f7420deae 100644 --- a/src/browser/documentation/sidebar-guides/styled.tsx +++ b/src/browser/documentation/sidebar-guides/styled.tsx @@ -3,9 +3,7 @@ import styled from 'styled-components' export const NoBulletsUl = styled.div` list-style-type: none; ` -export const BulletsInsideLi = styled.li` - list-style-position: inside; -` + export const MarginTopLi = styled.li` margin-top: 15px; ` diff --git a/src/browser/modules/Carousel/styled.tsx b/src/browser/modules/Carousel/styled.tsx index 9dbbec8d713..51c722f3e4a 100644 --- a/src/browser/modules/Carousel/styled.tsx +++ b/src/browser/modules/Carousel/styled.tsx @@ -437,6 +437,9 @@ export const StyledSidebarSlide = styled.div.attrs({ list-style-position: inside; padding-left: 0; margin-top: 0.5em; + p { + display: inline-block; + } } &.slide input { From 896990d711dc056065950320ad2f692401bc70ce Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Wed, 5 May 2021 11:04:54 +0200 Subject: [PATCH 02/16] Add padding so long guides don't love tail --- src/browser/modules/Sidebar/styled.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/modules/Sidebar/styled.tsx b/src/browser/modules/Sidebar/styled.tsx index c7ecf4c42ec..02af335ce06 100644 --- a/src/browser/modules/Sidebar/styled.tsx +++ b/src/browser/modules/Sidebar/styled.tsx @@ -128,7 +128,7 @@ export const StyledCommand = styled(DrawerBrowserCommand)` export const StyledCarousel = styled.div` height: 100%; - padding-bottom: 20px; + padding-bottom: 50px; width: 100%; outline: none; From 4a3edc7233bd88243e172615152124351750f270 Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Wed, 5 May 2021 11:31:56 +0200 Subject: [PATCH 03/16] Add fallback font to prevent ugly font loading effect --- src/browser/modules/Sidebar/NewSavedScript.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/modules/Sidebar/NewSavedScript.tsx b/src/browser/modules/Sidebar/NewSavedScript.tsx index c43c6a55d35..e5e912841fa 100644 --- a/src/browser/modules/Sidebar/NewSavedScript.tsx +++ b/src/browser/modules/Sidebar/NewSavedScript.tsx @@ -19,7 +19,7 @@ import React, { useState } from 'react' import styled from 'styled-components' const StyledHeaderText = styled.div` - font-family: 'Open Sans'; + font-family: ${props => props.theme.drawerHeaderFontFamily}; color: white; ` From ae25bfc89d51660193d6274eba7be7f4781b3f08 Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Wed, 5 May 2021 11:44:11 +0200 Subject: [PATCH 04/16] Disable font ligatures in sidebar --- src/browser/modules/GuideCarousel/GuideCarousel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/modules/GuideCarousel/GuideCarousel.tsx b/src/browser/modules/GuideCarousel/GuideCarousel.tsx index dab2a198811..ccb7204c64e 100644 --- a/src/browser/modules/GuideCarousel/GuideCarousel.tsx +++ b/src/browser/modules/GuideCarousel/GuideCarousel.tsx @@ -66,7 +66,7 @@ function GuidesCarousel({ const moreThanOneSlide = slides.length > 1 return ( - + {moreThanOneSlide && ( From 57c7808c6db1af4d04325e048ca6fb096a734bf4 Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Wed, 5 May 2021 12:18:50 +0200 Subject: [PATCH 05/16] Prevent one-click cypher --- src/browser/components/Directives.tsx | 6 ++++-- src/browser/documentation/sidebar-guides/concepts.tsx | 6 +++--- .../documentation/sidebar-guides/guideIndex.tsx | 10 +++++----- src/browser/documentation/sidebar-guides/intro.tsx | 2 +- .../documentation/sidebar-guides/movie-graph.tsx | 4 ++-- .../documentation/sidebar-guides/northwind-graph.tsx | 4 ++-- src/browser/documentation/sidebar-guides/unfound.tsx | 4 ++-- 7 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/browser/components/Directives.tsx b/src/browser/components/Directives.tsx index e4d714ff2f8..b825fed6555 100644 --- a/src/browser/components/Directives.tsx +++ b/src/browser/components/Directives.tsx @@ -31,7 +31,8 @@ const directives = [ { selector: '[data-exec]', valueExtractor: (elem: any) => { - return `${elem.getAttribute('data-exec')}` + // we prepend the : to only autoexec browser commands and not cypher + return `:${elem.getAttribute('data-exec')}` }, autoExec: true }, @@ -147,7 +148,8 @@ const mapDispatchToProps = (_dispatch: any, ownProps: any) => { return { onItemClick: (cmd: string, autoExec: boolean, id: string) => { if (!cmd.endsWith(' null') && !cmd.endsWith(':null')) { - if (autoExec) { + // prevent autorunning cypher by prefixing w :auto hack + if (autoExec && !cmd.startsWith(':auto')) { const action = executeCommand(cmd, { id, source: commandSources.button diff --git a/src/browser/documentation/sidebar-guides/concepts.tsx b/src/browser/documentation/sidebar-guides/concepts.tsx index 556d6f1853c..cdf6aeb5024 100644 --- a/src/browser/documentation/sidebar-guides/concepts.tsx +++ b/src/browser/documentation/sidebar-guides/concepts.tsx @@ -144,10 +144,10 @@ const slides = [

    Keep getting started

    • - Intro - a guided tour + Intro - a guided tour
    • - Cypher - query language + Cypher - query language
    • @@ -159,7 +159,7 @@ const slides = [

      Jump into code

      diff --git a/src/browser/documentation/sidebar-guides/guideIndex.tsx b/src/browser/documentation/sidebar-guides/guideIndex.tsx index 32cb1eca8ea..ad23635581b 100644 --- a/src/browser/documentation/sidebar-guides/guideIndex.tsx +++ b/src/browser/documentation/sidebar-guides/guideIndex.tsx @@ -22,26 +22,26 @@ const slides = [
    • - + :guide intro Navigating Neo4j Browser
    • - + :guide concepts Property graph model concepts - + :guide cypher Cypher basics - create, match, delete - + :guide movie-graph @@ -50,7 +50,7 @@ const slides = [ - + :guide northwind-graph Translate and import relation data into graph diff --git a/src/browser/documentation/sidebar-guides/intro.tsx b/src/browser/documentation/sidebar-guides/intro.tsx index d147be79424..ec5228f93a4 100644 --- a/src/browser/documentation/sidebar-guides/intro.tsx +++ b/src/browser/documentation/sidebar-guides/intro.tsx @@ -185,7 +185,7 @@ const slides = [

      Jump into code

      diff --git a/src/browser/documentation/sidebar-guides/movie-graph.tsx b/src/browser/documentation/sidebar-guides/movie-graph.tsx index beb664a6098..67b9627364c 100644 --- a/src/browser/documentation/sidebar-guides/movie-graph.tsx +++ b/src/browser/documentation/sidebar-guides/movie-graph.tsx @@ -742,11 +742,11 @@ RETURN tom, m, coActors, m2, cruise`}

      Next steps

      • - Northwind Graph- from RDBMS to + Northwind Graph- from RDBMS to graph
      • - Cypher- Learn Cypher syntax + Cypher- Learn Cypher syntax
      • diff --git a/src/browser/documentation/sidebar-guides/northwind-graph.tsx b/src/browser/documentation/sidebar-guides/northwind-graph.tsx index 0a6895aa9ec..cb31b315c4a 100644 --- a/src/browser/documentation/sidebar-guides/northwind-graph.tsx +++ b/src/browser/documentation/sidebar-guides/northwind-graph.tsx @@ -260,10 +260,10 @@ RETURN DISTINCT cust.contactName as CustomerName, SUM(o.quantity) AS TotalProduc

        Next steps


        diff --git a/src/browser/documentation/sidebar-guides/unfound.tsx b/src/browser/documentation/sidebar-guides/unfound.tsx index 9810e16aa08..c93a9268e54 100644 --- a/src/browser/documentation/sidebar-guides/unfound.tsx +++ b/src/browser/documentation/sidebar-guides/unfound.tsx @@ -28,11 +28,11 @@ const slides = [
        Try:
        • - :help - for general help about using Neo4j + :help - for general help about using Neo4j Browser
        • - :guide intro - to see a few available + :guide intro - to see a few available guides
        • From cbc35f621271dd9f03a111aecaeb2deb9e9a761d Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Thu, 6 May 2021 22:36:27 +0200 Subject: [PATCH 06/16] Add unstyled pagination component --- package.json | 1 - .../modules/GuideCarousel/GuideCarousel.tsx | 23 ++--- .../modules/GuideCarousel/Pagination.test.ts | 60 +++++++++++ .../modules/GuideCarousel/Pagination.tsx | 99 +++++++++++++++++++ 4 files changed, 166 insertions(+), 17 deletions(-) create mode 100644 src/browser/modules/GuideCarousel/Pagination.test.ts create mode 100644 src/browser/modules/GuideCarousel/Pagination.tsx diff --git a/package.json b/package.json index 26ab22f6866..7caeba000e3 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "e2e-local": "CYPRESS_E2E_TEST_ENV=\"local\" cypress run", "e2e-local-open": "CYPRESS_E2E_TEST_ENV=\"local\" cypress open", "format": "prettier-eslint --write 'src/**/!(*.min).{js,jsx,ts,tsx,css,json}' 'e2e_tests/**/*.{js,jsx,ts,tsx,css,json}' 'scripts/**/*.{js,jsx,ts,tsx,css,json}' 'build_scripts/**/*.{js,jsx,ts,tsx,css,json}'", - "jest": "jest --coverage", "lint": "eslint --fix --ext .ts --ext .tsx ./", "precommit": "lint-staged", "prepare-jar": "node ./scripts/prepare-mvn-package.js", diff --git a/src/browser/modules/GuideCarousel/GuideCarousel.tsx b/src/browser/modules/GuideCarousel/GuideCarousel.tsx index ccb7204c64e..407508effa5 100644 --- a/src/browser/modules/GuideCarousel/GuideCarousel.tsx +++ b/src/browser/modules/GuideCarousel/GuideCarousel.tsx @@ -26,9 +26,9 @@ import { GuideUl, StyledCarousel, GuideProgressContainer, - StyledProgressCount, - CarouselIndicator + StyledProgressCount } from '../Sidebar/styled' +import Pagination from './Pagination' type GuideCarouselProps = { slides: JSX.Element[] @@ -75,20 +75,11 @@ function GuidesCarousel({ - - {`${currentSlideIndex + 1} / ${slides.length}`} - - {slides.slice(0, 25).map((_, i) => ( - gotoSlide(i)} - active={i === currentSlideIndex} - > - - - ))} - {slides.length >= 25 && '...'} + diff --git a/src/browser/modules/GuideCarousel/Pagination.test.ts b/src/browser/modules/GuideCarousel/Pagination.test.ts new file mode 100644 index 00000000000..23cc5bbb1fa --- /dev/null +++ b/src/browser/modules/GuideCarousel/Pagination.test.ts @@ -0,0 +1,60 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import { paginationHelper } from './Pagination' + +const D = '...' +describe('Pagination', () => { + test('paginationHelper', () => { + // doesn't crash on out of bounds + expect(paginationHelper(0, 1)).toEqual([]) + + // Handles simple cases + expect(paginationHelper(0, 0)).toEqual([]) + expect(paginationHelper(3, 0)).toEqual([0, 1, 2]) + expect(paginationHelper(6, 4)).toEqual([0, 1, 2, 3, 4, 5]) + + // Same for list of 7 regardless of selection + Array.from({ length: 7 }).forEach((_a, i) => { + expect(paginationHelper(7, i)).toEqual([0, 1, 2, 3, 4, 5, 6]) + }) + + // Handles all cases length 8 + expect(paginationHelper(8, 0)).toEqual([0, 1, 2, 3, 4, D, 7]) + expect(paginationHelper(8, 1)).toEqual([0, 1, 2, 3, 4, D, 7]) + expect(paginationHelper(8, 2)).toEqual([0, 1, 2, 3, 4, D, 7]) + expect(paginationHelper(8, 3)).toEqual([0, 1, 2, 3, 4, D, 7]) + expect(paginationHelper(8, 4)).toEqual([0, D, 3, 4, 5, 6, 7]) + expect(paginationHelper(8, 5)).toEqual([0, D, 3, 4, 5, 6, 7]) + expect(paginationHelper(8, 6)).toEqual([0, D, 3, 4, 5, 6, 7]) + expect(paginationHelper(8, 7)).toEqual([0, D, 3, 4, 5, 6, 7]) + + // Handles all cases length 9 + expect(paginationHelper(9, 0)).toEqual([0, 1, 2, 3, 4, D, 8]) + expect(paginationHelper(9, 1)).toEqual([0, 1, 2, 3, 4, D, 8]) + expect(paginationHelper(9, 2)).toEqual([0, 1, 2, 3, 4, D, 8]) + expect(paginationHelper(9, 3)).toEqual([0, 1, 2, 3, 4, D, 8]) + expect(paginationHelper(9, 4)).toEqual([0, D, 3, 4, 5, D, 8]) + expect(paginationHelper(9, 5)).toEqual([0, D, 4, 5, 6, 7, 8]) + expect(paginationHelper(9, 6)).toEqual([0, D, 4, 5, 6, 7, 8]) + expect(paginationHelper(9, 7)).toEqual([0, D, 4, 5, 6, 7, 8]) + expect(paginationHelper(9, 8)).toEqual([0, D, 4, 5, 6, 7, 8]) + }) +}) diff --git a/src/browser/modules/GuideCarousel/Pagination.tsx b/src/browser/modules/GuideCarousel/Pagination.tsx new file mode 100644 index 00000000000..af0a3c5e8f1 --- /dev/null +++ b/src/browser/modules/GuideCarousel/Pagination.tsx @@ -0,0 +1,99 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import React from 'react' +type PaginationProps = { + gotoIndex: (index: number) => void + itemCount: number + selectedIndex: number +} +type DotDotDot = '...' + +const range = (from: number, to: number) => + Array.from({ length: from ? to - from + 1 : to }, (_, i) => i + from) + +export function paginationHelper( + itemCount: number, + selectedIndex: number +): (number | DotDotDot)[] { + /* Pagination example (C denotes current and blank steps replaced with ...) + C 2 3 4 5 9 + 1 C 3 4 5 9 + 1 2 C 4 5 9 + 1 2 3 C 5 9 + 1 4 C 6 9 + 1 5 C 7 8 9 + 1 5 6 C 8 9 + 1 5 6 7 C 9 + 1 5 6 7 8 C +*/ + const lastIndex = itemCount - 1 + const outOfBounds = selectedIndex < 0 || selectedIndex > lastIndex + if (outOfBounds) return [] + + const baseNumbers = range(0, itemCount) + // no split + if (itemCount <= 7) return baseNumbers + + // early splits + if (selectedIndex < 4) { + return [...range(0, 5), '...', lastIndex] + } + + // late splits + const isInlastFiveItems = itemCount - selectedIndex < 5 + if (isInlastFiveItems) { + return [0, '...', ...range(itemCount - 5, lastIndex)] + } + + // two splits + return [ + 0, + '...', + selectedIndex - 1, + selectedIndex, + selectedIndex + 1, + '...', + lastIndex + ] +} + +function Pagination({ + gotoIndex, + itemCount, + selectedIndex +}: PaginationProps): JSX.Element { + return ( + <> + {paginationHelper(itemCount, selectedIndex).map((symbol, index) => { + if (symbol === '...') { + return + } else { + return ( + gotoIndex(symbol)}> + {symbol + 1} + + ) + } + })} + + ) +} +export default Pagination From c730d6f48bc970fc2b1d5dcc62c04faa266459b4 Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Thu, 6 May 2021 22:51:00 +0200 Subject: [PATCH 07/16] Update comment --- .../modules/GuideCarousel/Pagination.tsx | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/browser/modules/GuideCarousel/Pagination.tsx b/src/browser/modules/GuideCarousel/Pagination.tsx index af0a3c5e8f1..23e4c620bc3 100644 --- a/src/browser/modules/GuideCarousel/Pagination.tsx +++ b/src/browser/modules/GuideCarousel/Pagination.tsx @@ -33,16 +33,17 @@ export function paginationHelper( itemCount: number, selectedIndex: number ): (number | DotDotDot)[] { - /* Pagination example (C denotes current and blank steps replaced with ...) - C 2 3 4 5 9 - 1 C 3 4 5 9 - 1 2 C 4 5 9 - 1 2 3 C 5 9 - 1 4 C 6 9 - 1 5 C 7 8 9 - 1 5 6 C 8 9 - 1 5 6 7 C 9 - 1 5 6 7 8 C + /* We aim to always show 7 symbols + Pagination example (C denotes current index and D denotes dots) + C 2 3 4 5 D 9 + 1 C 3 4 5 D 9 + 1 2 C 4 5 D 9 + 1 2 3 C 5 D 9 + 1 D 4 C 6 D 9 + 1 D 5 C 7 8 9 + 1 D 5 6 C 8 9 + 1 D 5 6 7 C 9 + 1 D 5 6 7 8 C */ const lastIndex = itemCount - 1 const outOfBounds = selectedIndex < 0 || selectedIndex > lastIndex From 51da156951f692dc50f16a4e74cf3687aeeb8c1f Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Fri, 7 May 2021 11:35:48 +0200 Subject: [PATCH 08/16] Style pagination --- src/browser/modules/GuideCarousel/GuideCarousel.tsx | 3 +-- src/browser/modules/GuideCarousel/Pagination.tsx | 9 +++++++-- src/browser/modules/GuideCarousel/styled.tsx | 7 +++++++ 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 src/browser/modules/GuideCarousel/styled.tsx diff --git a/src/browser/modules/GuideCarousel/GuideCarousel.tsx b/src/browser/modules/GuideCarousel/GuideCarousel.tsx index 407508effa5..cf49935b4d6 100644 --- a/src/browser/modules/GuideCarousel/GuideCarousel.tsx +++ b/src/browser/modules/GuideCarousel/GuideCarousel.tsx @@ -25,8 +25,7 @@ import { GuideNavButton, GuideUl, StyledCarousel, - GuideProgressContainer, - StyledProgressCount + GuideProgressContainer } from '../Sidebar/styled' import Pagination from './Pagination' diff --git a/src/browser/modules/GuideCarousel/Pagination.tsx b/src/browser/modules/GuideCarousel/Pagination.tsx index 23e4c620bc3..1aa9db9f7e9 100644 --- a/src/browser/modules/GuideCarousel/Pagination.tsx +++ b/src/browser/modules/GuideCarousel/Pagination.tsx @@ -19,6 +19,7 @@ */ import React from 'react' +import { PaginationItem } from 'semantic-ui-react' type PaginationProps = { gotoIndex: (index: number) => void itemCount: number @@ -88,9 +89,13 @@ function Pagination({ return } else { return ( - gotoIndex(symbol)}> + gotoIndex(symbol)} + > {symbol + 1} - + ) } })} diff --git a/src/browser/modules/GuideCarousel/styled.tsx b/src/browser/modules/GuideCarousel/styled.tsx new file mode 100644 index 00000000000..bbc8ecd98a2 --- /dev/null +++ b/src/browser/modules/GuideCarousel/styled.tsx @@ -0,0 +1,7 @@ +import styled from 'styled-components' + +export const PaginationItem = styled.span<{ active: boolean }>` + padding: 0 3px; + ${props => (props.active ? 'color: white;' : null)} + cursor: pointer; +` From 0facc6e5c1c3f6051a77a913286563a76c81f8cb Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Fri, 7 May 2021 12:19:51 +0200 Subject: [PATCH 09/16] Add e2e tests --- e2e_tests/integration/guide-command.spec.ts | 93 +++++++++++++++++++ .../modules/GuideCarousel/GuideCarousel.tsx | 12 ++- .../modules/GuideCarousel/Pagination.tsx | 32 ++++--- src/browser/modules/Sidebar/GuidesDrawer.tsx | 8 +- 4 files changed, 127 insertions(+), 18 deletions(-) create mode 100644 e2e_tests/integration/guide-command.spec.ts diff --git a/e2e_tests/integration/guide-command.spec.ts b/e2e_tests/integration/guide-command.spec.ts new file mode 100644 index 00000000000..5f4ea2dbb4b --- /dev/null +++ b/e2e_tests/integration/guide-command.spec.ts @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002-2021 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* global Cypress, cy, before */ + +describe('Play command', () => { + before(function() { + cy.visit(Cypress.config('url')) + .title() + .should('include', 'Neo4j Browser') + cy.wait(3000) + }) + + it('handles not found guides', () => { + cy.executeCommand(':clear') + cy.executeCommand(':guide not-found-guide-anywhere') + + cy.get('[data-testid="guideDrawer"]').should('contain', 'Not found') + + // reset state + cy.executeCommand(':guide') + cy.get('[data-testid="guideDrawer"]').should('contain', ':guide movie') + cy.get('[data-testid=drawerGuides]').click() + }) + + it('can walk through a guides', () => { + cy.executeCommand(':clear') + // Open a guide from the sidebar + cy.get('[data-testid=drawerGuides]').click() + cy.get('[data-testid="guideDrawer"]') + .contains(':guide cypher') + .click() + + // can progress slide + cy.get('[data-testid=guideNextSlide]').click() + cy.get('[data-testid="guideDrawer"]').contains('CREATE') + + // remembers slide location + cy.get('[data-testid=drawerGuides]').click() + cy.get('[data-testid=drawerGuides]').click() + + // can go back + cy.get('[data-testid="guideDrawer"]').contains('CREATE') + cy.get('[data-testid=guidePreviousSlide]').click() + cy.get('[data-testid="guideDrawer"]').contains('SQL-like clauses') + + // go to end + cy.get('[data-testid=guideNextSlide]').click() + cy.get('[data-testid=guideNextSlide]').click() + cy.get('[data-testid=guideNextSlide]').click() + cy.get('[data-testid=guideNextSlide]').click() + cy.get('[data-testid=guideNextSlide]').click() + cy.get('[data-testid=guideNextSlide]').click() + cy.get('[data-testid=guideNextSlide]').click() + cy.get('[data-testid=guideNextSlide]').click() + cy.get('[data-testid="guideDrawer"]').contains('Next steps') + + // switch guide via command + cy.executeCommand(':guide northwind') + cy.get('[data-testid="guideDrawer"]').contains('From RDBMS to Graph') + + // Jump to end, then new guide + cy.get('[data-testid="pagination-7"]').click() + cy.get('[data-testid="guideDrawer"]') + .contains('Movie Graph') + .click() + + cy.get('[data-testid="guideDrawer"]').contains('mini graph application') + + // Can use back button + cy.get('[data-testid="guidesBackButton"]').click() + cy.get('[data-testid="guideDrawer"]').contains(':guide cypher') + + cy.get('[data-testid=drawerGuides]').click() + }) +}) diff --git a/src/browser/modules/GuideCarousel/GuideCarousel.tsx b/src/browser/modules/GuideCarousel/GuideCarousel.tsx index cf49935b4d6..408fccfd5bc 100644 --- a/src/browser/modules/GuideCarousel/GuideCarousel.tsx +++ b/src/browser/modules/GuideCarousel/GuideCarousel.tsx @@ -69,7 +69,11 @@ function GuidesCarousel({ {moreThanOneSlide && ( - + Previous @@ -81,7 +85,11 @@ function GuidesCarousel({ /> - + Next diff --git a/src/browser/modules/GuideCarousel/Pagination.tsx b/src/browser/modules/GuideCarousel/Pagination.tsx index 1aa9db9f7e9..dc2eaa8e1c4 100644 --- a/src/browser/modules/GuideCarousel/Pagination.tsx +++ b/src/browser/modules/GuideCarousel/Pagination.tsx @@ -84,21 +84,25 @@ function Pagination({ }: PaginationProps): JSX.Element { return ( <> - {paginationHelper(itemCount, selectedIndex).map((symbol, index) => { - if (symbol === '...') { - return - } else { - return ( - gotoIndex(symbol)} - > - {symbol + 1} - - ) + {paginationHelper(itemCount, selectedIndex).map( + (slideIndexOrDots, index) => { + if (slideIndexOrDots === '...') { + return + } else { + const displayNumber = slideIndexOrDots + 1 + return ( + gotoIndex(slideIndexOrDots)} + data-testid={`pagination-${displayNumber}`} + > + {displayNumber} + + ) + } } - })} + )} ) } diff --git a/src/browser/modules/Sidebar/GuidesDrawer.tsx b/src/browser/modules/Sidebar/GuidesDrawer.tsx index 539c56c3e8d..b98a8c0131e 100644 --- a/src/browser/modules/Sidebar/GuidesDrawer.tsx +++ b/src/browser/modules/Sidebar/GuidesDrawer.tsx @@ -54,10 +54,14 @@ function GuidesDrawer({ const scrollRef = useRef(null) return ( - + {!isDefaultGuide(guide) && ( - + )} From d4c120b88e24e90faffbe582f5753ce3942672b9 Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Fri, 7 May 2021 12:34:33 +0200 Subject: [PATCH 10/16] Re-add jest script --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 7caeba000e3..26ab22f6866 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "e2e-local": "CYPRESS_E2E_TEST_ENV=\"local\" cypress run", "e2e-local-open": "CYPRESS_E2E_TEST_ENV=\"local\" cypress open", "format": "prettier-eslint --write 'src/**/!(*.min).{js,jsx,ts,tsx,css,json}' 'e2e_tests/**/*.{js,jsx,ts,tsx,css,json}' 'scripts/**/*.{js,jsx,ts,tsx,css,json}' 'build_scripts/**/*.{js,jsx,ts,tsx,css,json}'", + "jest": "jest --coverage", "lint": "eslint --fix --ext .ts --ext .tsx ./", "precommit": "lint-staged", "prepare-jar": "node ./scripts/prepare-mvn-package.js", From fb3f5c2377c054544ac0cc72086684f20dae4f75 Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Fri, 7 May 2021 12:41:01 +0200 Subject: [PATCH 11/16] Update snapshot --- .../__snapshots__/index.test.tsx.snap | 6 +- .../__snapshots__/ErrorsView.test.tsx.snap | 38 +++++----- .../VisualizationView.test.tsx.snap | 4 +- .../__snapshots__/SchemaFrame.test.tsx.snap | 72 +++++++++---------- 4 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/browser/modules/ClickToCode/__snapshots__/index.test.tsx.snap b/src/browser/modules/ClickToCode/__snapshots__/index.test.tsx.snap index 88d2e8b5964..421dcebf36e 100644 --- a/src/browser/modules/ClickToCode/__snapshots__/index.test.tsx.snap +++ b/src/browser/modules/ClickToCode/__snapshots__/index.test.tsx.snap @@ -5,7 +5,7 @@ exports[`ClickToCode does not render if no children 1`] = `
          `; exports[`ClickToCode renders all children 1`] = `
          @@ -20,7 +20,7 @@ exports[`ClickToCode renders all children 1`] = ` exports[`ClickToCode renders children as code if no code is provided 1`] = `
          hellohi! @@ -30,7 +30,7 @@ exports[`ClickToCode renders children as code if no code is provided 1`] = ` exports[`ClickToCode renders code as the code when code is available 1`] = `
          hello diff --git a/src/browser/modules/Stream/CypherFrame/__snapshots__/ErrorsView.test.tsx.snap b/src/browser/modules/Stream/CypherFrame/__snapshots__/ErrorsView.test.tsx.snap index 9f56e1c40d2..2289f6b263b 100644 --- a/src/browser/modules/Stream/CypherFrame/__snapshots__/ErrorsView.test.tsx.snap +++ b/src/browser/modules/Stream/CypherFrame/__snapshots__/ErrorsView.test.tsx.snap @@ -6,11 +6,11 @@ exports[`ErrorsViews ErrorsStatusbar displays error 1`] = ` class="sc-bdVaJa kwzqrW" > Test.Error: Test error description @@ -26,42 +26,42 @@ exports[`ErrorsViews ErrorsView displays nothing if no errors 1`] = `
          `; exports[`ErrorsViews ErrorsView displays procedure link if unknown procedure 1`] = `
          ERROR

          Neo.ClientError.Procedure.ProcedureNotFound

                     not found
                   
           List available procedures @@ -74,30 +74,30 @@ exports[`ErrorsViews ErrorsView displays procedure link if unknown procedure 1`] exports[`ErrorsViews ErrorsView does displays an error 1`] = `
          ERROR

          Test.Error

                     Test error description
                   
          diff --git a/src/browser/modules/Stream/CypherFrame/__snapshots__/VisualizationView.test.tsx.snap b/src/browser/modules/Stream/CypherFrame/__snapshots__/VisualizationView.test.tsx.snap index 2ef4d565da8..350069ace36 100644 --- a/src/browser/modules/Stream/CypherFrame/__snapshots__/VisualizationView.test.tsx.snap +++ b/src/browser/modules/Stream/CypherFrame/__snapshots__/VisualizationView.test.tsx.snap @@ -137,7 +137,7 @@ exports[`Visualization renders with result and escapes any HTML 1`] = ` class="sc-cvbbAY ZoyPP faded zoom-in" > @@ -145,7 +145,7 @@ exports[`Visualization renders with result and escapes any HTML 1`] = ` class="sc-cvbbAY ZoyPP zoom-out" > diff --git a/src/browser/modules/Stream/__snapshots__/SchemaFrame.test.tsx.snap b/src/browser/modules/Stream/__snapshots__/SchemaFrame.test.tsx.snap index e7c725018de..a2b4f418f87 100644 --- a/src/browser/modules/Stream/__snapshots__/SchemaFrame.test.tsx.snap +++ b/src/browser/modules/Stream/__snapshots__/SchemaFrame.test.tsx.snap @@ -10,13 +10,13 @@ exports[`SchemaFrame renders empty 1`] = ` class="sc-ibxdXY lnvWNA" > @@ -24,10 +24,10 @@ exports[`SchemaFrame renders empty 1`] = ` @@ -35,13 +35,13 @@ exports[`SchemaFrame renders empty 1`] = `
          Indexes
          None
          @@ -49,10 +49,10 @@ exports[`SchemaFrame renders empty 1`] = ` @@ -92,43 +92,43 @@ exports[`SchemaFrame renders empty for Neo4j >= 4.0 1`] = ` class="sc-ibxdXY lnvWNA" >
          Constraints
          None
          @@ -136,42 +136,42 @@ exports[`SchemaFrame renders empty for Neo4j >= 4.0 1`] = `
          Index Name Type Uniqueness EntityType LabelsOrTypes Properties State
          None
          @@ -179,10 +179,10 @@ exports[`SchemaFrame renders empty for Neo4j >= 4.0 1`] = ` @@ -222,13 +222,13 @@ exports[`SchemaFrame renders results for Neo4j < 4.0 1`] = ` class="sc-ibxdXY lnvWNA" >
          Constraints
          None
          @@ -236,10 +236,10 @@ exports[`SchemaFrame renders results for Neo4j < 4.0 1`] = ` @@ -247,13 +247,13 @@ exports[`SchemaFrame renders results for Neo4j < 4.0 1`] = `
          Indexes
          ON :Movie(released) ONLINE
          @@ -261,10 +261,10 @@ exports[`SchemaFrame renders results for Neo4j < 4.0 1`] = ` From a94e8e36de4252b921d6d5f7f1f13121cf5bbb6d Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Fri, 7 May 2021 14:27:01 +0200 Subject: [PATCH 12/16] Mistaken import --- src/browser/modules/GuideCarousel/Pagination.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/modules/GuideCarousel/Pagination.tsx b/src/browser/modules/GuideCarousel/Pagination.tsx index dc2eaa8e1c4..75889adf93e 100644 --- a/src/browser/modules/GuideCarousel/Pagination.tsx +++ b/src/browser/modules/GuideCarousel/Pagination.tsx @@ -19,7 +19,7 @@ */ import React from 'react' -import { PaginationItem } from 'semantic-ui-react' +import { PaginationItem } from './styled' type PaginationProps = { gotoIndex: (index: number) => void itemCount: number From c8d3e8db5924e9cd8a305e3c7bdf87e84dc7d14d Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Fri, 7 May 2021 20:39:38 +0200 Subject: [PATCH 13/16] Autorun on clicking small arrow --- src/browser/components/Directives.tsx | 13 ++++++++++--- src/shared/services/dom-helpers.ts | 9 +++++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/browser/components/Directives.tsx b/src/browser/components/Directives.tsx index b825fed6555..c7ec60c9624 100644 --- a/src/browser/components/Directives.tsx +++ b/src/browser/components/Directives.tsx @@ -87,8 +87,8 @@ const directives = [ } ] -const prependPlayIcon = (element: any) => { - prependIcon(element, 'fa fa-play-circle-o') +const prependPlayIcon = (element: any, onClick: () => void) => { + prependIcon(element, 'fa fa-play-circle-o', onClick) } const bindDynamicInputToDom = (element: any) => { @@ -123,7 +123,14 @@ export const Directives = (props: any) => { e.firstChild?.nodeName !== 'I' && !e.classList.contains('remove-play-icon') ) { - prependPlayIcon(e) + prependPlayIcon(e, () => { + addClass(e, 'clicked') + props.onItemClick( + directive.valueExtractor(e), + true, + props.originFrameId + ) + }) } // If we use add event listener we need to remove it afterwards diff --git a/src/shared/services/dom-helpers.ts b/src/shared/services/dom-helpers.ts index d3452a90513..e9463dca035 100644 --- a/src/shared/services/dom-helpers.ts +++ b/src/shared/services/dom-helpers.ts @@ -18,7 +18,6 @@ * along with this program. If not, see . */ -/* global HTMLElement */ const addClass = (node: any, className: any) => { if (!(node instanceof HTMLElement && typeof className === 'string')) { return @@ -31,11 +30,17 @@ const addClass = (node: any, className: any) => { } } -const prependIcon = (element: any, classname: any) => { +const prependIcon = (element: any, classname: string, onClick: () => void) => { const icon = document.createElement('i') addClass(icon, classname) icon.setAttribute('style', 'padding-right:4px') element.insertBefore(icon, element.firstChild) + onClick && + icon.addEventListener('click', e => { + // prevent populating the editor as well + e.stopPropagation() + onClick() + }) } export { addClass, prependIcon } From 80b2b6750d21ce8e1dbd8f5d7bb9464c87d33c6e Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Fri, 7 May 2021 21:15:53 +0200 Subject: [PATCH 14/16] Fix review comments --- e2e_tests/integration/guide-command.spec.ts | 2 +- src/browser/modules/GuideCarousel/Pagination.tsx | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/e2e_tests/integration/guide-command.spec.ts b/e2e_tests/integration/guide-command.spec.ts index 5f4ea2dbb4b..5a8e48c85e6 100644 --- a/e2e_tests/integration/guide-command.spec.ts +++ b/e2e_tests/integration/guide-command.spec.ts @@ -20,7 +20,7 @@ /* global Cypress, cy, before */ -describe('Play command', () => { +describe('Guide command', () => { before(function() { cy.visit(Cypress.config('url')) .title() diff --git a/src/browser/modules/GuideCarousel/Pagination.tsx b/src/browser/modules/GuideCarousel/Pagination.tsx index 75889adf93e..a8021e0c337 100644 --- a/src/browser/modules/GuideCarousel/Pagination.tsx +++ b/src/browser/modules/GuideCarousel/Pagination.tsx @@ -25,7 +25,8 @@ type PaginationProps = { itemCount: number selectedIndex: number } -type DotDotDot = '...' +const DOTS = '...' +type DotDotDot = typeof DOTS const range = (from: number, to: number) => Array.from({ length: from ? to - from + 1 : to }, (_, i) => i + from) @@ -56,23 +57,23 @@ export function paginationHelper( // early splits if (selectedIndex < 4) { - return [...range(0, 5), '...', lastIndex] + return [...range(0, 5), DOTS, lastIndex] } // late splits const isInlastFiveItems = itemCount - selectedIndex < 5 if (isInlastFiveItems) { - return [0, '...', ...range(itemCount - 5, lastIndex)] + return [0, DOTS, ...range(itemCount - 5, lastIndex)] } // two splits return [ 0, - '...', + DOTS, selectedIndex - 1, selectedIndex, selectedIndex + 1, - '...', + DOTS, lastIndex ] } @@ -86,7 +87,7 @@ function Pagination({ <> {paginationHelper(itemCount, selectedIndex).map( (slideIndexOrDots, index) => { - if (slideIndexOrDots === '...') { + if (slideIndexOrDots === DOTS) { return } else { const displayNumber = slideIndexOrDots + 1 From 61845a4a3b971eb9901c07b2f8bfe9b5def83a88 Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Mon, 10 May 2021 11:06:30 +0200 Subject: [PATCH 15/16] Move brackets --- src/browser/modules/GuideCarousel/Pagination.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/browser/modules/GuideCarousel/Pagination.tsx b/src/browser/modules/GuideCarousel/Pagination.tsx index a8021e0c337..2da5848c126 100644 --- a/src/browser/modules/GuideCarousel/Pagination.tsx +++ b/src/browser/modules/GuideCarousel/Pagination.tsx @@ -49,11 +49,16 @@ export function paginationHelper( */ const lastIndex = itemCount - 1 const outOfBounds = selectedIndex < 0 || selectedIndex > lastIndex - if (outOfBounds) return [] + if (outOfBounds) { + return [] + } const baseNumbers = range(0, itemCount) + // no split - if (itemCount <= 7) return baseNumbers + if (itemCount <= 7) { + return baseNumbers + } // early splits if (selectedIndex < 4) { From ba9a881417b03716acaf23001825eaa844f6467f Mon Sep 17 00:00:00 2001 From: Oskar Damkjaer Date: Mon, 10 May 2021 11:28:13 +0200 Subject: [PATCH 16/16] Avoid mem-leak --- src/browser/components/Directives.tsx | 4 +--- src/shared/services/dom-helpers.ts | 8 +++++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/browser/components/Directives.tsx b/src/browser/components/Directives.tsx index c7ec60c9624..4ecf367b520 100644 --- a/src/browser/components/Directives.tsx +++ b/src/browser/components/Directives.tsx @@ -117,7 +117,7 @@ export const Directives = (props: any) => { const callback = (elem: HTMLDivElement | null) => { if (elem) { directives.forEach(directive => { - const elems = elem.querySelectorAll(directive.selector) + const elems = elem.querySelectorAll(directive.selector) Array.from(elems).forEach(e => { if ( e.firstChild?.nodeName !== 'I' && @@ -133,8 +133,6 @@ export const Directives = (props: any) => { }) } - // If we use add event listener we need to remove it afterwards - // @ts-expect-error e.onclick = () => { addClass(e, 'clicked') return props.onItemClick( diff --git a/src/shared/services/dom-helpers.ts b/src/shared/services/dom-helpers.ts index e9463dca035..a3ba69069f4 100644 --- a/src/shared/services/dom-helpers.ts +++ b/src/shared/services/dom-helpers.ts @@ -35,12 +35,14 @@ const prependIcon = (element: any, classname: string, onClick: () => void) => { addClass(icon, classname) icon.setAttribute('style', 'padding-right:4px') element.insertBefore(icon, element.firstChild) - onClick && - icon.addEventListener('click', e => { + + if (onClick) { + icon.onclick = e => { // prevent populating the editor as well e.stopPropagation() onClick() - }) + } + } } export { addClass, prependIcon }
          Constraints
          ON ( book:Book ) ASSERT book.isbn IS UNIQUE