diff --git a/.eslintrc.json b/.eslintrc.json
index 6f7a0eccf..c6d98d2c6 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -4,7 +4,8 @@
"extends": ["eslint:recommended", "prettier", "plugin:@typescript-eslint/recommended"], // this is optional
"env": {
"browser": true,
- "node": true
+ "node": true,
+ "jest": true
},
"settings": {
"react": {
@@ -166,5 +167,9 @@
],
"symbol-description": "error",
"yoda": "error"
+ },
+ "globals": {
+ "cy": "readonly",
+ "Cypress": "readonly"
}
}
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 000000000..8f7a92ae3
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,19 @@
+version: 2
+updates:
+ - package-ecosystem: 'npm'
+ directory: '/'
+ schedule:
+ interval: 'weekly'
+ target-branch: 'develop'
+
+ - package-ecosystem: 'npm'
+ directory: '/gallery'
+ schedule:
+ interval: 'weekly'
+ target-branch: 'develop'
+
+ - package-ecosystem: 'npm'
+ directory: '/docs'
+ schedule:
+ interval: 'weekly'
+ target-branch: 'develop'
diff --git a/.github/workflows/master-deployment.yml b/.github/workflows/master-deployment.yml
index 55cf525c4..820b12d8c 100644
--- a/.github/workflows/master-deployment.yml
+++ b/.github/workflows/master-deployment.yml
@@ -79,7 +79,7 @@ jobs:
context: .
file: ./Dockerfile
push: true
- tags: ${{ secrets.DOCKER_HUB_LABS_USERNAME }}/neodash:latest,${{ secrets.DOCKER_HUB_LABS_USERNAME }}/neodash:2.4.8
+ tags: ${{ secrets.DOCKER_HUB_LABS_USERNAME }}/neodash:latest,${{ secrets.DOCKER_HUB_LABS_USERNAME }}/neodash:2.4.9
build-docker-legacy:
needs: build-test
runs-on: neodash-runners
@@ -103,7 +103,7 @@ jobs:
context: .
file: ./Dockerfile
push: true
- tags: ${{ secrets.DOCKER_HUB_USERNAME }}/neodash:latest,${{ secrets.DOCKER_HUB_USERNAME }}/neodash:2.4.8
+ tags: ${{ secrets.DOCKER_HUB_USERNAME }}/neodash:latest,${{ secrets.DOCKER_HUB_USERNAME }}/neodash:2.4.9
deploy-gallery:
runs-on: neodash-runners
strategy:
diff --git a/Dockerfile b/Dockerfile
index 44320dcaf..a31be8d85 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -44,4 +44,4 @@ USER nginx
EXPOSE $NGINX_PORT
HEALTHCHECK cmd curl --fail "http://localhost:$NGINX_PORT" || exit 1
-LABEL version="2.4.8"
+LABEL version="2.4.9"
diff --git a/README.md b/README.md
index 5c4db07c9..7ba0e71da 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,24 @@
-## NeoDash - Neo4j Dashboard Builder
-NeoDash is an open source tool for visualizing your Neo4j data. It lets you group visualizations together as dashboards, and allow for interactions between reports.
+## NeoDash Labs - Neo4j Dashboard Builder
-![screenshot](public/screenshot.png)
+![screenshot](evolving.png)
+
+In September 2024 **Neo4j [announced](https://www.datanami.com/2024/09/04/neo4j-simplifies-graph-database-in-the-cloud/#:~:text=NeoDash%20is%20an%20open%20source,was%20open%20source%2C%20not%20supported) NeoDash is evolving into a fully supported dashboard builder, as part of the Neo4j product suite**.
+
+This project (NeoDash Labs) will still be available and contain experimental features, but will **not** have official support. If you're interested to get official support for NeoDash as part of a Neo4j License agreement, please reach out to your Neo4j contact person.
+
+## About NeoDash Labs
+NeoDash is a web-based tool for visualizing your Neo4j data. It lets you group visualizations together as dashboards, and allow for interactions between reports.
Neodash supports presenting your data as tables, graphs, bar charts, line charts, maps and more. It contains a Cypher editor to directly write the Cypher queries that populate the reports. You can save dashboards to your database, and share them with others.
-## Try NeoDash
+## Try NeoDash Labs
You can run NeoDash in one of three ways:
-1. You can install NeoDash into Neo4j Desktop from the [graph app gallery](https://install.graphapp.io). NeoDash will automatically connect to your active database.
-2. You can run NeoDash from a web browser by visiting http://neodash.graphapp.io.
+1. You can install NeoDash Labs into Neo4j Desktop from the [graph app gallery](https://install.graphapp.io). NeoDash will automatically connect to your active database.
+> Note: never versions of Neo4j Desktop do not support adding experimental graph apps such as NeoDash.
+
+2. You can run NeoDash Labs from a web browser by visiting http://neodash.graphapp.io.
3. For on-prem deployments, you can build the application yourself, or pull the latest Docker image from Docker Hub.
```
# Run the application on http://localhost:5005
@@ -79,4 +87,4 @@ If you have any questions about NeoDash, please reach out to the maintainers:
- Connect with us on the [Neo4j Discord](https://neo4j.com/developer/discord/).
- Create a post on the Neo4j [Community Forum](https://community.neo4j.com/).
-> NeoDash is a free and open-source tool developed by the Neo4j community - not an official Neo4j product. If you have a need for a commercial agreement around training, custom extensions or other services, please contact the [Neo4j Professional Services](https://neo4j.com/professional-services/) team.
\ No newline at end of file
+> NeoDash Labs is a free and open-source tool developed by the Neo4j community - not an official Neo4j product. Use at your own risk!
\ No newline at end of file
diff --git a/changelog.md b/changelog.md
index ae99c6f96..9227e1fff 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,23 @@
+## NeoDash 2.4.9
+This release adds some minor changes to documentation and implements some community contributions.
+- Added notice about project evolution: [#967](https://github.com/neo4j-labs/neodash/pull/967)
+- Added community contributions and bug fixes:
+[#967](https://github.com/neo4j-labs/neodash/pull/967)
+[#894](https://github.com/neo4j-labs/neodash/pull/894)
+[#822](https://github.com/neo4j-labs/neodash/pull/822)
+[#951](https://github.com/neo4j-labs/neodash/pull/951)
+[#946](https://github.com/neo4j-labs/neodash/pull/946)
+[#944](https://github.com/neo4j-labs/neodash/pull/944)
+[#943](https://github.com/neo4j-labs/neodash/pull/943)
+[#938](https://github.com/neo4j-labs/neodash/pull/938)
+[#935](https://github.com/neo4j-labs/neodash/pull/935)
+[#918](https://github.com/neo4j-labs/neodash/pull/918)
+[#908](https://github.com/neo4j-labs/neodash/pull/908)
+[#906](https://github.com/neo4j-labs/neodash/pull/906)
+[#902](https://github.com/neo4j-labs/neodash/pull/902)
+[#895](https://github.com/neo4j-labs/neodash/pull/895)
+[#893](https://github.com/neo4j-labs/neodash/pull/893)
+
## NeoDash 2.4.8
This is a minor release containing an important fix and other minor fixes:
diff --git a/cypress.config.ts b/cypress.config.ts
index 73948909e..93f8cffdf 100644
--- a/cypress.config.ts
+++ b/cypress.config.ts
@@ -5,6 +5,7 @@ export default defineConfig({
projectId: 'a8nh14',
video: false,
e2e: {
+ defaultCommandTimeout: 20000,
experimentalMemoryManagement: true,
numTestsKeptInMemory: 0,
baseUrl: 'http://localhost:3000',
diff --git a/cypress/Page.js b/cypress/Page.js
new file mode 100644
index 000000000..f90742a41
--- /dev/null
+++ b/cypress/Page.js
@@ -0,0 +1,156 @@
+const DB_URL = 'localhost';
+const DB_USERNAME = 'neo4j';
+const DB_PASSWORD = 'test1234';
+
+export class Page {
+ constructor(cardSelector) {
+ this.cardSelector = cardSelector;
+ }
+
+ init() {
+ cy.viewport(1920, 1080);
+ cy.visit('/', {
+ onBeforeLoad(win) {
+ win.localStorage.clear();
+ },
+ });
+ return this;
+ }
+
+ createNewDashboard() {
+ cy.get('#form-dialog-title').then(($div) => {
+ const text = $div.text();
+ if (text == 'NeoDash - Neo4j Dashboard Builder') {
+ cy.wait(100);
+ // Create new dashboard
+ cy.contains('New Dashboard').click();
+ }
+ });
+ return this;
+ }
+
+ connectToNeo4j() {
+ cy.get('#form-dialog-title', { timeout: 20000 }).should('contain', 'Connect to Neo4j');
+ cy.get('#url').clear().type(DB_URL);
+ cy.get('#dbusername').clear().type(DB_USERNAME);
+ cy.get('#dbpassword').type(DB_PASSWORD);
+ cy.get('button').contains('Connect').click();
+ cy.wait(100);
+ return this;
+ }
+
+ enableReportActions() {
+ cy.get('main button[aria-label="Extensions').should('be.visible').click();
+ cy.get('#checkbox-actions').scrollIntoView();
+ cy.get('#checkbox-actions').should('be.visible').click();
+ cy.get('.ndl-dialog-close').scrollIntoView().should('be.visible').click();
+ cy.wait(100);
+ return this;
+ }
+
+ enableAdvancedVisualizations() {
+ cy.get('main button[aria-label="Extensions').should('be.visible').click();
+ cy.get('#checkbox-advanced-charts').should('be.visible').click();
+ cy.get('.ndl-dialog-close').scrollIntoView().should('be.visible').click();
+ cy.wait(100);
+ return this;
+ }
+
+ enableFormsExtension() {
+ cy.get('main button[aria-label="Extensions').should('be.visible').click();
+ cy.get('#checkbox-forms').scrollIntoView();
+ cy.get('#checkbox-forms').should('be.visible').click();
+ cy.get('.ndl-dialog-close').scrollIntoView().should('be.visible').click();
+ cy.wait(100);
+ return this;
+ }
+
+ selectReportOfType(type) {
+ cy.get('main .react-grid-item button[aria-label="add report"]').should('be.visible').click();
+ cy.get('main .react-grid-item')
+ .contains('No query specified.')
+ .parentsUntil('.react-grid-item')
+ .find('button[aria-label="settings"]', { timeout: 2000 })
+ .should('be.visible')
+ .click();
+ cy.get(`${this.cardSelector} #type`, { timeout: 2000 }).should('be.visible').click();
+ cy.contains(type).click();
+ cy.wait(100);
+ return this;
+ }
+
+ createReportOfType(type, query, fast = false, run = true) {
+ this.selectReportOfType(type);
+ if (fast) {
+ cy.get(`${this.cardSelector} .ReactCodeMirror`).type(query, {
+ delay: 1,
+ parseSpecialCharSequences: false,
+ });
+ } else {
+ cy.get(`${this.cardSelector} .ReactCodeMirror`).type(query, { parseSpecialCharSequences: false });
+ }
+ cy.wait(400);
+
+ if (run) {
+ this.closeSettings();
+ }
+
+ cy.wait(100);
+ return this;
+ }
+
+ openSettings() {
+ cy.get(this.cardSelector).find('button[aria-label="settings"]', { WAITING_TIME: 2000 }).click();
+ cy.wait(100);
+ return this;
+ }
+
+ closeSettings() {
+ cy.get(`${this.cardSelector} button[aria-label="run"]`).click();
+ cy.wait(100);
+ return this;
+ }
+
+ openAdvancedSettings() {
+ this.openSettings();
+ cy.get(this.cardSelector).contains('Advanced settings').click();
+ cy.wait(100);
+ return this;
+ }
+
+ closeAdvancedSettings() {
+ cy.get(this.cardSelector).contains('Advanced settings').click();
+ this.closeSettings();
+ return this;
+ }
+
+ openReportActionsMenu() {
+ this.openSettings();
+ cy.get(this.cardSelector).find('button[aria-label="custom actions"]').click();
+ cy.wait(100);
+ return this;
+ }
+
+ updateDropdownAdvancedSetting(settingLabel, targetValue) {
+ this.openAdvancedSettings();
+ cy.get(`${this.cardSelector} .ndl-dropdown`).contains(settingLabel).siblings('div').click();
+ cy.contains(targetValue).click();
+ this.closeAdvancedSettings();
+ return this;
+ }
+
+ updateChartQuery(query) {
+ this.openSettings();
+
+ cy.get(this.cardSelector)
+ .find('.ndl-cypher-editor div[role="textbox"]')
+ .should('be.visible')
+ .click()
+ .clear()
+ .type(query);
+ cy.wait(100);
+
+ this.closeSettings();
+ return this;
+ }
+}
diff --git a/cypress/e2e/bar_chart.cy.js b/cypress/e2e/bar_chart.cy.js
deleted file mode 100644
index 3f9c20faa..000000000
--- a/cypress/e2e/bar_chart.cy.js
+++ /dev/null
@@ -1,316 +0,0 @@
-import { barChartCypherQuery } from '../fixtures/cypher_queries';
-
-const WAITING_TIME = 20000;
-// Ignore warnings that may appear when using the Cypress dev server
-Cypress.on('uncaught:exception', (err, runnable) => {
- console.log(err, runnable);
- return false;
-});
-
-describe('Testing bar chart', () => {
- beforeEach('open neodash', () => {
- cy.viewport(1920, 1080);
- cy.visit('/', {
- onBeforeLoad(win) {
- win.localStorage.clear();
- },
- });
-
- cy.get('#form-dialog-title', { timeout: 20000 }).should('contain', 'NeoDash - Neo4j Dashboard Builder').click();
-
- cy.get('#form-dialog-title').then(($div) => {
- const text = $div.text();
- if (text == 'NeoDash - Neo4j Dashboard Builder') {
- cy.wait(500);
- // Create new dashboard
- cy.contains('New Dashboard').click();
- }
- });
-
- cy.get('#form-dialog-title', { timeout: 20000 }).should('contain', 'Connect to Neo4j');
-
- cy.get('#url').clear().type('localhost');
- cy.get('#dbusername').clear().type('neo4j');
- cy.get('#dbpassword').type('test1234');
- cy.get('button').contains('Connect').click();
- cy.wait(100);
-
- //Opens the div containing all report cards
- cy.get('.react-grid-layout:eq(0)').within(() => {
- //Finds the 2nd card
- cy.get('.MuiGrid-root')
- .eq(1)
- .within(() => {
- //Clicks the 2nd button (opens settings)
- cy.get('button').eq(1).click();
- });
- });
- cy.get('.react-grid-layout:eq(0)').within(() => {
- //Finds the 2nd card
- cy.get('.MuiGrid-root')
- .eq(1)
- .within(() => {
- //Opens the drop down
- cy.getDataTest('type-dropdown').click();
- });
- });
- // Selects the Bar option
- cy.get('[id^="react-select-5-option"]')
- .contains(/Bar Chart/i)
- .should('be.visible')
- .click({ force: true });
- cy.get('.react-grid-layout .MuiGrid-root:eq(1) #type input[name="Type"]').should('have.value', 'Bar Chart');
-
- // Creates basic bar chart
- cy.get('.react-grid-layout')
- .first()
- .within(() => {
- //Finds the 2nd card
- cy.get('.MuiGrid-root')
- .eq(1)
- .within(() => {
- //Removes text in cypher editor and types new query
- cy.get('.ndl-cypher-editor div[role="textbox"]')
- .should('be.visible')
- .click()
- .clear()
- .type(barChartCypherQuery);
-
- cy.wait(400);
- cy.get('button[aria-label="run"]').click();
- });
- });
-
- cy.wait(500);
- });
-
- it.skip('Checking Colour Picker settings', () => {
- //Opens advanced settings
- cy.get('.react-grid-layout')
- .first()
- .within(() => {
- //Finds the 2nd card
- cy.get('.MuiGrid-root')
- .eq(1)
- .within(() => {
- // Access advanced settings
- cy.get('button').eq(1).click();
- cy.get('[role="switch"]').click();
- cy.wait(200);
- // Changing setting for colour picker
- cy.get('[data-testid="colorpicker-input"]').find('input').click().type('{selectall}').type('red');
- cy.get('button[aria-label="run"]').click();
- // Checking that colour picker was applied correctly
- cy.get('.card-view').should('have.css', 'background-color', 'rgb(255, 0, 0)');
- cy.wait(200);
- // Changing colour back to white
- cy.get('button').eq(1).click();
- cy.get('[data-testid="colorpicker-input"]').find('input').click().type('{selectall}').type('white');
- cy.get('button[aria-label="run"]').click();
- // Checking colour has been set back to white
- cy.wait(200);
- cy.get('.card-view').should('have.css', 'background-color', 'rgb(255, 255, 255)');
- });
- });
- });
-
- it.skip('Checking Selector Description', () => {
- //Opens first 2nd card
- cy.get('.react-grid-layout:eq(0) .MuiGrid-root:eq(1)').within(() => {
- // Access advanced settings
- cy.get('button').eq(1).click();
- cy.get('[role="switch"]').click();
- cy.wait(200);
- // Changing Selector Description to 'Test'
- cy.get('.ndl-textarea').contains('span', 'Selector Description').click().type('Test');
- cy.get('button[aria-label="run"]').click();
- // Pressing Selector Description button
- cy.get('button[aria-label="details"]').click();
- });
- // Checking that Selector Description is behaving as expected
- cy.get('.MuiDialog-paper').should('be.visible').and('contain.text', 'Test');
- cy.wait(1000);
-
- // Click elsewhere on the page to close dialog box
- cy.get('div[role="dialog"]').parent().click(-100, -100, { force: true });
- });
-
- it.skip('Checking full screen bar chart setting', () => {
- //Opens first 2nd card
- cy.get('.react-grid-layout:eq(0) .MuiGrid-root:eq(1)').within(() => {
- // Opening settings
- cy.get('button').eq(1).click();
- // Activating advanced settings
- cy.get('[role="switch"]').click();
- cy.wait(200);
- // Finding fullscreen setting and changing it to 'on'
- cy.get('.ndl-dropdown')
- .contains('label', 'Fullscreen enabled')
- .scrollIntoView()
- .should('be.visible')
- .click()
- .type('on{enter}');
- // Pressing run to return to card view
- cy.get('button[aria-label="run"]').click();
- cy.get('button[aria-label="maximize"]').click();
- });
- // Modal outside of scope of card
- // Checking existence of full-screen modal
- cy.get('.dialog-xxl').should('be.visible');
- // Action to close full-screen modal
- cy.get('button[aria-label="un-maximize"]').click();
- // Checking that fullscreen has un-maximized
- // Check that the div is no longer in the DOM
- cy.get('div[data-focus-lock-disabled="false"]').should('not.exist');
- });
-
- it.skip('Checking "Autorun Query" works as intended', () => {
- // Custom command to open advanced settings
- cy.advancedSettings(() => {
- // Finding 'Auto-run query setting and changing it to 'off'
- cy.get('.ndl-dropdown')
- .contains('label', 'Auto-run query')
- .scrollIntoView()
- .should('be.visible')
- .click()
- .type('off{enter}');
- cy.wait(200);
- cy.get('button[aria-label="run"]').click();
- cy.get('.ndl-cypher-editor').should('be.visible');
- cy.get('g').should('not.exist');
- cy.wait(100);
- cy.get('.MuiCardContent-root').find('button[aria-label="run"]').filter(':visible').click();
- cy.get('g').should('exist');
- });
- });
-
- it.skip('Checking Legend integration works as intended', () => {
- cy.advancedSettings(() => {
- // Checking that legend appears
- cy.setDropdownValue('Show Legend', 'on');
- cy.wait(100);
- cy.get('button[aria-label="run"]').click();
- cy.wait(100);
- //Checking that legend matches value specified: in the case - 'count'
- cy.get('svg g g text').last().contains(/count/i);
- });
- cy.advancedSettings(() => {
- // Activating advanced settings
- cy.get('[role="switch"]').click();
- // Checking that legend disappears
- cy.setDropdownValue('Show Legend', 'off');
- cy.wait(100);
- cy.get('button[aria-label="run"]').click();
- cy.wait(100);
- cy.get('svg g g text').last().contains(/count/i).should('not.exist');
- });
- });
-
- it.skip('Checking the stacked grouping function works as intended', () => {
- cy.advancedSettings(() => {
- cy.get('.ndl-cypher-editor div[role="textbox"]')
- .should('be.visible')
- .click()
- .clear()
- .type(
- 'MATCH (p:Person)-[:DIRECTED]->(n:Movie) RETURN n.released AS released, p.name AS Director, count(n.title) AS count LIMIT 5'
- );
- cy.setDropdownValue('Grouping', 'on');
- cy.wait(100);
- cy.get('button[aria-label="run"]').click();
- cy.get('.ndl-dropdown:contains("Group")').find('svg').parent().click().type('Director{enter}');
- // Checking that the groups are stacked
- cy.get('.MuiCardContent-root')
- .find('g')
- .children('g')
- .eq(3) // Get the fourth g element (index starts from 0)
- .invoke('attr', 'transform')
- .then((transformValue) => {
- // Captures the first number in the tranlsate attribute using the parenthisis to capture the first digit and put it in the second value of the resulting array
- // if transformValue is translate(100,200), then transformValue.match(/translate\((\d+),\d+\)/) will produce an array like ["translate(100,200)", "100"],
- const match = transformValue.match(/translate\((\d+),\d+\)/);
- if (match?.[1]) {
- const xValue = match[1];
- console.log('xValue: ', xValue);
-
- // Now find sibling g elements with the same x transform value
- cy.get('.MuiCardContent-root')
- .find('g')
- .children('g')
- .filter((index, element) => {
- const siblingTransform = Cypress.$(element).attr('transform');
- return siblingTransform?.includes(`translate(${xValue},`);
- })
- .should('have.length', 3); // Check that there's at least one element
- } else {
- throw new Error('Transform attribute not found or invalid format');
- }
- });
- });
- cy.get('.ndl-dropdown:contains("Group")').find('svg').parent().click().type('(none){enter}');
- // Checking that the stacked grouped elements do not exist
- cy.get('.MuiCardContent-root')
- .find('g')
- .children('g')
- .eq(3) // Get the fourth g element (index starts from 0)
- .invoke('attr', 'transform')
- .then((transformValue) => {
- // Captures the first number in the tranlsate attribute using the parenthisis to capture the first digit and put it in the second value of the resulting array
- // if transformValue is translate(100,200), then transformValue.match(/translate\((\d+),\d+\)/) will produce an array like ["translate(100,200)", "100"],
- const match = transformValue.match(/translate\((\d+),\d+\)/);
- if (match?.[1]) {
- const xValue = match[1];
- console.log('xValue: ', xValue);
-
- // Now find sibling g elements with the same x transform value
- cy.get('.MuiCardContent-root')
- .find('g')
- .children('g')
- .filter((index, element) => {
- const siblingTransform = Cypress.$(element).attr('transform');
- return siblingTransform?.includes(`translate(${xValue},`);
- })
- .should('have.length', 1); // Check that there are no matching elements
- } else {
- throw new Error('Transform attribute not found or invalid format');
- }
- });
- });
-
- // How to properly test this?
- it.skip('Testing grouped grouping mode', () => {
- cy.advancedSettings(() => {
- cy.get('.ndl-cypher-editor div[role="textbox"]')
- .should('be.visible')
- .click()
- .clear()
- .type(
- 'MATCH (p:Person)-[:DIRECTED]->(n:Movie) RETURN n.released AS released, p.name AS Director, count(n.title) AS count LIMIT 5'
- );
- cy.setDropdownValue('Grouping', 'on');
- cy.setDropdownValue('Group Mode', 'grouped');
- cy.wait(400);
- cy.get('button[aria-label="run"]').click();
- cy.get('.ndl-dropdown:contains("Group")').find('svg').parent().click().type('Director{enter}');
- });
- });
-
- it.skip('Testing "Show Value on Bars"', () => {
- cy.advancedSettings(() => {
- cy.setDropdownValue('Show Values On Bars', 'on');
- cy.get('button[aria-label="run"]').click();
- cy.get('.MuiCardContent-root')
- .find('div svg > g > g > text')
- .should('have.length', 5)
- .then((textElements) => {
- cy.log('Number of text elements:', textElements.length);
- });
- });
- cy.wait(100);
- cy.openSettings(() => {
- cy.setDropdownValue('Show Values On Bars', 'off');
- cy.get('button[aria-label="run"]').click();
- cy.get('.MuiCardContent-root').find('div svg > g > g > text').should('not.exist');
- });
- });
-});
diff --git a/cypress/e2e/render/array.cy.js b/cypress/e2e/charts/array.cy.js
similarity index 70%
rename from cypress/e2e/render/array.cy.js
rename to cypress/e2e/charts/array.cy.js
index 108d4aceb..1da231f01 100644
--- a/cypress/e2e/render/array.cy.js
+++ b/cypress/e2e/charts/array.cy.js
@@ -1,17 +1,9 @@
import { stringArrayCypherQuery, intArrayCypherQuery, pathArrayCypherQuery } from '../../fixtures/cypher_queries';
-import {
- enableReportActions,
- createReportOfType,
- closeSettings,
- toggleTableTranspose,
- openReportActionsMenu,
- selectReportOfType,
- openAdvancedSettings,
- updateDropdownAdvancedSetting,
-} from '../utils';
+import { Page } from '../../Page';
-const WAITING_TIME = 20000;
const CARD_SELECTOR = 'main .react-grid-item:eq(2)';
+const page = new Page(CARD_SELECTOR);
+
// Ignore warnings that may appear when using the Cypress dev server
Cypress.on('uncaught:exception', (err, runnable) => {
console.log(err, runnable);
@@ -20,62 +12,34 @@ Cypress.on('uncaught:exception', (err, runnable) => {
describe('Testing array rendering', () => {
beforeEach('open neodash', () => {
- cy.viewport(1920, 1080);
- cy.visit('/', {
- onBeforeLoad(win) {
- win.localStorage.clear();
- },
- });
-
- cy.get('#form-dialog-title', { WAITING_TIME: WAITING_TIME })
- .should('contain', 'NeoDash - Neo4j Dashboard Builder')
- .click();
-
- cy.get('#form-dialog-title').then(($div) => {
- const text = $div.text();
- if (text == 'NeoDash - Neo4j Dashboard Builder') {
- cy.wait(500);
- // Create new dashboard
- cy.contains('New Dashboard').click();
- }
- });
-
- cy.get('#form-dialog-title', { WAITING_TIME: WAITING_TIME }).should('contain', 'Connect to Neo4j');
-
- cy.get('#url').clear().type('localhost');
- cy.get('#dbusername').clear().type('neo4j');
- cy.get('#dbpassword').type('test1234');
- cy.get('button').contains('Connect').click();
+ page.init().createNewDashboard().connectToNeo4j();
cy.wait(100);
});
it('creates a table that contains string arrays', () => {
cy.checkInitialState();
- enableReportActions();
- createReportOfType('Table', stringArrayCypherQuery, true, true);
+ page.enableReportActions();
+ page.createReportOfType('Table', stringArrayCypherQuery, true, true);
// Standard array, displays strings joined with comma and whitespace
cy.get(`${CARD_SELECTOR} .MuiDataGrid-cell:eq(0)`).should('have.text', 'initial, list');
cy.get(`${CARD_SELECTOR} .MuiDataGrid-cell:eq(1)`).should('have.text', 'other, list');
// Now, transpose the table
- toggleTableTranspose(CARD_SELECTOR, true);
- cy.get(`${CARD_SELECTOR} .MuiDataGrid-columnHeaderTitle:eq(1)`, { timeout: WAITING_TIME }).should(
- 'have.text',
- 'initial,list'
- );
+ page.updateDropdownAdvancedSetting('Transpose Rows & Columns', 'on');
+ cy.get(`${CARD_SELECTOR} .MuiDataGrid-columnHeaderTitle:eq(1)`).should('have.text', 'initial,list');
cy.get(`${CARD_SELECTOR} .MuiDataGrid-cell:eq(1)`).should('have.text', 'other, list');
// Transpose back
// And add a report action
- toggleTableTranspose(CARD_SELECTOR, false);
- openReportActionsMenu(CARD_SELECTOR);
+ page.updateDropdownAdvancedSetting('Transpose Rows & Columns', 'off');
+ page.openReportActionsMenu();
cy.get('.ndl-modal').find('button[aria-label="add"]').click();
cy.get('.ndl-modal').find('input:eq(2)').type('column');
cy.get('.ndl-modal').find('input:eq(5)').type('test_param');
cy.get('.ndl-modal').find('input:eq(6)').type('column');
cy.get('.ndl-modal').find('button').contains('Save').click();
- closeSettings(CARD_SELECTOR);
+ page.closeSettings();
cy.get(`${CARD_SELECTOR} .MuiDataGrid-cell:eq(0)`)
.find('button')
.should('be.visible')
@@ -90,24 +54,21 @@ describe('Testing array rendering', () => {
it('creates a table that contains int arrays', () => {
cy.checkInitialState();
- createReportOfType('Table', intArrayCypherQuery, true, true);
+ page.createReportOfType('Table', intArrayCypherQuery, true, true);
// Standard array, displays strings joined with comma and whitespace
cy.get(`${CARD_SELECTOR} .MuiDataGrid-cell:eq(0)`).should('have.text', '1, 2');
cy.get(`${CARD_SELECTOR} .MuiDataGrid-cell:eq(1)`).should('have.text', '3, 4');
// Now, transpose the table
- toggleTableTranspose(CARD_SELECTOR, true);
- cy.get(`${CARD_SELECTOR} .MuiDataGrid-columnHeaderTitle:eq(1)`, { timeout: WAITING_TIME }).should(
- 'have.text',
- '1,2'
- );
+ page.updateDropdownAdvancedSetting('Transpose Rows & Columns', 'on');
+ cy.get(`${CARD_SELECTOR} .MuiDataGrid-columnHeaderTitle:eq(1)`).should('have.text', '1,2');
cy.get(`${CARD_SELECTOR} .MuiDataGrid-cell:eq(1)`).should('have.text', '3, 4');
});
it('creates a table that contains nodes and rels', () => {
cy.checkInitialState();
- createReportOfType('Table', pathArrayCypherQuery, true, true);
+ page.createReportOfType('Table', pathArrayCypherQuery, true, true);
// Standard array, displays a path with two nodes and a relationship
cy.get(`${CARD_SELECTOR} .MuiDataGrid-cell:eq(0)`).should('have.text', 'PersonACTED_INMovie');
@@ -120,13 +81,13 @@ describe('Testing array rendering', () => {
it('creates a single value report which is an array', () => {
cy.checkInitialState();
- createReportOfType('Single Value', stringArrayCypherQuery, true, true);
+ page.createReportOfType('Single Value', stringArrayCypherQuery, true, true);
cy.get(CARD_SELECTOR).should('have.text', 'initial, list');
});
it('creates a multi parameter select', () => {
cy.checkInitialState();
- selectReportOfType('Parameter Select');
+ page.selectReportOfType('Parameter Select');
cy.get('main .react-grid-item:eq(2) label[for="Selection Type"]').siblings('div').click();
// Set up the parameter select
cy.contains('Node Property').click();
@@ -140,8 +101,8 @@ describe('Testing array rendering', () => {
cy.wait(1000);
cy.get('.MuiAutocomplete-popper').contains('title').click();
// Enable multiple selection
- closeSettings(CARD_SELECTOR);
- updateDropdownAdvancedSetting(CARD_SELECTOR, 'Multiple Selection', 'on');
+ page.closeSettings();
+ page.updateDropdownAdvancedSetting('Multiple Selection', 'on');
// Finally, select a few values in the parameter select
cy.get(CARD_SELECTOR).contains('Movie title').click();
cy.get(CARD_SELECTOR).contains('Movie title').siblings('div').find('input').type('a');
diff --git a/cypress/e2e/charts/bar.cy.js b/cypress/e2e/charts/bar.cy.js
new file mode 100644
index 000000000..80f13d640
--- /dev/null
+++ b/cypress/e2e/charts/bar.cy.js
@@ -0,0 +1,211 @@
+import { barChartCypherQuery } from '../../fixtures/cypher_queries';
+import { Page } from '../../Page';
+
+const CARD_SELECTOR = '.react-grid-layout:eq(0) .MuiGrid-root:eq(2)';
+const page = new Page(CARD_SELECTOR);
+
+// Ignore warnings that may appear when using the Cypress dev server
+Cypress.on('uncaught:exception', (err, runnable) => {
+ console.log(err, runnable);
+ return false;
+});
+
+describe('Testing bar chart', () => {
+ beforeEach('open neodash', () => {
+ page.init().createNewDashboard().connectToNeo4j().createReportOfType('Bar Chart', barChartCypherQuery);
+ });
+
+ it('Checking Colour Picker settings', () => {
+ //Opens advanced settings
+ cy.get('.react-grid-layout')
+ .first()
+ .within(() => {
+ //Finds the 2nd card
+ cy.get('.MuiGrid-root:eq(2)').within(() => {
+ // Access advanced settings
+ cy.get('button').eq(1).click();
+ cy.get('[role="switch"]').click();
+ cy.wait(200);
+ // Changing setting for colour picker
+ cy.get('[data-testid="colorpicker-input"]').find('input').click().type('{selectall}').type('red');
+ cy.get('button[aria-label="run"]').click();
+ // Checking that colour picker was applied correctly
+ cy.get('.card-view').should('have.css', 'background-color', 'rgb(255, 0, 0)');
+ cy.wait(200);
+ // Changing colour back to white
+ cy.get('button').eq(1).click();
+ cy.get('[data-testid="colorpicker-input"]').find('input').click().type('{selectall}').type('white');
+ cy.get('button[aria-label="run"]').click();
+ // Checking colour has been set back to white
+ cy.wait(200);
+ cy.get('.card-view').should('have.css', 'background-color', 'rgb(255, 255, 255)');
+ });
+ });
+ });
+
+ it('Checking Selector Description', () => {
+ //Opens first 2nd card
+ cy.get('.react-grid-layout:eq(0) .MuiGrid-root:eq(2)').within(() => {
+ // Access advanced settings
+ cy.get('button').eq(1).click();
+ cy.get('[role="switch"]').click();
+ cy.wait(200);
+ // Changing Selector Description to 'Test'
+ cy.get('.ndl-textarea').contains('span', 'Selector Description').click().type('Test');
+ cy.get('button[aria-label="run"]').click();
+ // Pressing Selector Description button
+ cy.get('button[aria-label="details"]').click();
+ });
+ // Checking that Selector Description is behaving as expected
+ cy.get('.MuiDialog-paper').should('be.visible').and('contain.text', 'Test');
+ cy.wait(1000);
+
+ // Click elsewhere on the page to close dialog box
+ cy.get('div[role="dialog"]').parent().click(-100, -100, { force: true });
+ });
+
+ it('Checking full screen bar chart setting', () => {
+ page.updateDropdownAdvancedSetting('Fullscreen enabled', 'on');
+ cy.get('button[aria-label="maximize"]').click();
+ // Checking existence of full-screen modal
+ cy.get('.dialog-xxl').should('be.visible');
+ // Action to close full-screen modal
+ cy.get('button[aria-label="un-maximize"]').click();
+ // Checking that fullscreen has un-maximized
+ // Check that the div is no longer in the DOM
+ cy.get('div[data-focus-lock-disabled="false"]').should('not.exist');
+ });
+
+ it('Checking "Autorun Query" works as intended', () => {
+ page.updateDropdownAdvancedSetting('Auto-run query', 'off');
+ cy.get('.MuiCardContent-root').find('.ndl-cypher-editor').should('be.visible');
+ cy.get('.MuiCardContent-root').find('g').should('not.exist');
+ cy.wait(100);
+ cy.get('.MuiCardContent-root').find('button[aria-label="run"]').filter(':visible').click();
+ cy.get('g').should('exist');
+ });
+
+ it('Checking Legend integration works as intended', () => {
+ page.updateDropdownAdvancedSetting('Show Legend', 'on');
+ // Checking that legend matches value specified: in the case - 'count'
+ cy.get('svg g g text').last().contains(/count/i);
+
+ page.updateDropdownAdvancedSetting('Show Legend', 'off');
+ cy.get('svg g g text').last().contains(/count/i).should('not.exist');
+ });
+
+ it('Checking the stacked grouping function works as intended', () => {
+ const TRANSLATE_REGEXP = /translate\(([0-9]{1,3}), [0-9]{1,3}\)/;
+
+ page
+ .updateChartQuery(
+ 'MATCH (p:Person)-[:DIRECTED]->(n:Movie) RETURN n.released AS released, p.name AS Director, count(n.title) AS count LIMIT 5'
+ )
+ .updateDropdownAdvancedSetting('Grouping', 'on');
+
+ cy.get('.MuiGrid-root:eq(2)')
+ .find('.ndl-dropdown:contains("Group")')
+ .find('svg')
+ .parent()
+ .click()
+ .type('Director{enter}');
+ // Checking that the groups are stacked
+ cy.get('.MuiGrid-root:eq(2)')
+ .find('g')
+ .children('g')
+ .eq(3) // Get the fourth g element (index starts from 0)
+ .invoke('attr', 'transform')
+ .then((transformValue) => {
+ // Captures the first number in the translate attribute using the parenthesis to capture the first digit and put it in the second value of the resulting array
+ // if transformValue is translate(100,200), then it will produce an array like ["translate(100,200)", "100"],
+ const match = transformValue.match(TRANSLATE_REGEXP);
+ if (match?.[1]) {
+ const xValue = match[1];
+ // Now find sibling g elements with the same x transform value
+ cy.get('.MuiCardContent-root')
+ .find('g')
+ .children('g')
+ .filter((_, element) => {
+ const siblingTransform = Cypress.$(element).attr('transform');
+ return siblingTransform?.includes(`translate(${xValue},`);
+ })
+ .should('have.length', 3); // Check that there's at least one element
+ } else {
+ throw new Error('Transform attribute not found or invalid format');
+ }
+ });
+ cy.get('.ndl-dropdown:contains("Group")').find('svg').parent().click().type('(none){enter}');
+ //Checking that the stacked grouped elements do not exist
+ cy.get('.MuiCardContent-root')
+ .find('g')
+ .children('g')
+ .eq(3) // Get the fourth g element (index starts from 0)
+ .invoke('attr', 'transform')
+ .then((transformValue) => {
+ // Captures the first number in the translate attribute using the parenthesis to capture the first digit and put it in the second value of the resulting array
+ // if transformValue is translate(100,200), then it will produce an array like ["translate(100,200)", "100"],
+ const match = transformValue.match(TRANSLATE_REGEXP);
+ if (match?.[1]) {
+ const xValue = match[1];
+ // Now find sibling g elements with the same x transform value
+ cy.get('.MuiCardContent-root')
+ .find('g')
+ .children('g')
+ .filter((_, element) => {
+ const siblingTransform = Cypress.$(element).attr('transform');
+ return siblingTransform?.includes(`translate(${xValue},`);
+ })
+ .should('have.length', 1); // Check that there are no matching elements
+ } else {
+ throw new Error('Transform attribute not found or invalid format');
+ }
+ });
+ });
+
+ // How to properly test this?
+ it.skip('Testing grouped grouping mode', () => {
+ page
+ .updateChartQuery(
+ 'MATCH (p:Person)-[:DIRECTED]->(n:Movie) RETURN n.released AS released, p.name AS Director, count(n.title) AS count LIMIT 5'
+ )
+ .updateDropdownAdvancedSetting('Grouping', 'on')
+ .updateDropdownAdvancedSetting('Group Mode', 'grouped');
+ cy.get('.ndl-dropdown:contains("Group")').find('svg').parent().click().type('Director{enter}');
+ });
+
+ it('Testing "Show Value on Bars"', () => {
+ page.updateDropdownAdvancedSetting('Show Values On Bars', 'on');
+ cy.get('.react-grid-layout:eq(0) .MuiGrid-root:eq(2)').find('div svg > g > g > text').should('have.length', 5);
+
+ page.updateDropdownAdvancedSetting('Show Values On Bars', 'off');
+ cy.get('.react-grid-layout:eq(0) .MuiGrid-root:eq(2)').find('div svg > g > g > text').should('not.exist');
+ });
+
+ describe('Y axis display', () => {
+ it('Checking Y axis is displayed', () => {
+ page.updateDropdownAdvancedSetting('Display Y axis', 'on');
+ cy.get('.MuiCardContent-root svg > g > g:nth-child(3)')
+ .invoke('attr', 'transform')
+ .should('eq', 'translate(0,0)');
+ });
+
+ it('Checking Y axis is hidden', () => {
+ page.updateDropdownAdvancedSetting('Display Y axis', 'off');
+ cy.get('.MuiCardContent-root svg > g > g:nth-child(3)')
+ .invoke('attr', 'transform')
+ .should('not.eq', 'translate(0,0)');
+ });
+ });
+
+ describe('Y grid lines display', () => {
+ it('Checking Y grid lines are displayed', () => {
+ page.updateDropdownAdvancedSetting('Display Y grid lines', 'on');
+ cy.get('.MuiCardContent-root svg g > g > line').invoke('attr', 'stroke').should('eq', '#dddddd');
+ });
+
+ it('Checking Y grid lines are hidden', () => {
+ page.updateDropdownAdvancedSetting('Display Y grid lines', 'off');
+ cy.get('.MuiCardContent-root svg g > g > line').invoke('attr', 'stroke').should('not.eq', '#dddddd');
+ });
+ });
+});
diff --git a/cypress/e2e/table.cy.js b/cypress/e2e/charts/table.cy.js
similarity index 66%
rename from cypress/e2e/table.cy.js
rename to cypress/e2e/charts/table.cy.js
index 8ae2ac3c8..5c086df1b 100644
--- a/cypress/e2e/table.cy.js
+++ b/cypress/e2e/charts/table.cy.js
@@ -1,6 +1,7 @@
-import { tableCypherQuery } from '../fixtures/cypher_queries';
+import { tableCypherQuery } from '../../fixtures/cypher_queries';
+import { Page } from '../../Page';
-const WAITING_TIME = 20000;
+const page = new Page();
// Ignore warnings that may appear when using the Cypress dev server
Cypress.on('uncaught:exception', (err, runnable) => {
console.log(err, runnable);
@@ -9,30 +10,7 @@ Cypress.on('uncaught:exception', (err, runnable) => {
describe('Testing table', () => {
beforeEach('open neodash', () => {
- cy.viewport(1920, 1080);
- cy.visit('/', {
- onBeforeLoad(win) {
- win.localStorage.clear();
- },
- });
-
- cy.get('#form-dialog-title', { timeout: 20000 }).should('contain', 'NeoDash - Neo4j Dashboard Builder').click();
-
- cy.get('#form-dialog-title').then(($div) => {
- const text = $div.text();
- if (text == 'NeoDash - Neo4j Dashboard Builder') {
- cy.wait(500);
- // Create new dashboard
- cy.contains('New Dashboard').click();
- }
- });
-
- cy.get('#form-dialog-title', { timeout: 20000 }).should('contain', 'Connect to Neo4j');
-
- cy.get('#url').clear().type('localhost');
- cy.get('#dbusername').clear().type('neo4j');
- cy.get('#dbpassword').type('test1234');
- cy.get('button').contains('Connect').click();
+ page.init().createNewDashboard().connectToNeo4j();
cy.wait(100);
});
diff --git a/cypress/e2e/start_page.cy.js b/cypress/e2e/start_page.cy.js
index c6e9f7c4b..8038866b3 100644
--- a/cypress/e2e/start_page.cy.js
+++ b/cypress/e2e/start_page.cy.js
@@ -10,9 +10,12 @@ import {
gaugeChartCypherQuery,
formCypherQuery,
} from '../fixtures/cypher_queries';
-import { createReportOfType, selectReportOfType, enableAdvancedVisualizations, enableFormsExtension } from './utils';
-const WAITING_TIME = 20000;
+import { Page } from '../Page';
+
+const CARD_SELECTOR = 'main .react-grid-item:eq(2)';
+const page = new Page(CARD_SELECTOR);
+
// Ignore warnings that may appear when using the Cypress dev server
Cypress.on('uncaught:exception', (err, runnable) => {
console.log(err, runnable);
@@ -21,40 +24,7 @@ Cypress.on('uncaught:exception', (err, runnable) => {
describe('NeoDash E2E Tests', () => {
beforeEach(() => {
- cy.viewport(1920, 1080);
- // Navigate to index
- cy.visit('/', {
- onBeforeLoad(win) {
- win.localStorage.clear();
- },
- });
-
- cy.get('#form-dialog-title', { timeout: 20000 }).should('contain', 'NeoDash - Neo4j Dashboard Builder').click();
-
- cy.get('#form-dialog-title').then(($div) => {
- const text = $div.text();
- if (text == 'NeoDash - Neo4j Dashboard Builder') {
- cy.wait(500);
- // Create new dashboard
- cy.contains('New Dashboard').click();
- }
- });
-
- // If an old dashboard exists in cache, do a check to make sure we clear it.
- // if (cy.contains("Create new dashboard")) {
- // cy.contains('Yes').click()
- // }
-
- cy.get('#form-dialog-title', { timeout: 20000 }).should('contain', 'Connect to Neo4j');
-
- // Connect to Neo4j database
- // cy.get('#protocol').click()
- // cy.contains('neo4j').click()
- cy.get('#url').clear().type('localhost');
- // cy.get('#database').type('neo4j')
- cy.get('#dbusername').clear().type('neo4j');
- cy.get('#dbpassword').type('test1234');
- cy.get('button').contains('Connect').click();
+ page.init().createNewDashboard().connectToNeo4j();
cy.wait(100);
});
@@ -85,7 +55,7 @@ describe('NeoDash E2E Tests', () => {
cy.get('main .react-grid-item:eq(2)').contains('Advanced settings').click();
cy.get('main .react-grid-item:eq(2) button[aria-label="run"]').click();
- cy.get('main .react-grid-item:eq(2) .MuiDataGrid-columnHeaders', { timeout: WAITING_TIME })
+ cy.get('main .react-grid-item:eq(2) .MuiDataGrid-columnHeaders')
.should('contain', 'title')
.and('contain', 'released')
.and('not.contain', '__id');
@@ -98,34 +68,25 @@ describe('NeoDash E2E Tests', () => {
it('creates a bar chart report', () => {
cy.checkInitialState();
- createReportOfType('Bar Chart', barChartCypherQuery);
- cy.get('main .react-grid-item:eq(2) #index input[name="Category"]', { timeout: WAITING_TIME }).should(
- 'have.value',
- 'released'
- );
+ page.createReportOfType('Bar Chart', barChartCypherQuery);
+ cy.get('main .react-grid-item:eq(2) #index input[name="Category"]').should('have.value', 'released');
cy.get('main .react-grid-item:eq(2) #value input[name="Value"]').should('have.value', 'count');
cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > g').should('have.length', 8);
});
it('creates a pie chart report', () => {
cy.checkInitialState();
- createReportOfType('Pie Chart', barChartCypherQuery);
- cy.get('main .react-grid-item:eq(2) #index input[name="Category"]', { timeout: WAITING_TIME }).should(
- 'have.value',
- 'released'
- );
+ page.createReportOfType('Pie Chart', barChartCypherQuery);
+ cy.get('main .react-grid-item:eq(2) #index input[name="Category"]').should('have.value', 'released');
cy.get('main .react-grid-item:eq(2) #value input[name="Value"]').should('have.value', 'count');
cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > g').should('have.length', 3);
- cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > g:nth-child(2) > path').should('have.length', 5);
+ cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > g > path').should('have.length', 5);
});
it('creates a line chart report', () => {
cy.checkInitialState();
- createReportOfType('Line Chart', barChartCypherQuery);
- cy.get('main .react-grid-item:eq(2) #x input[name="X-value"]', { timeout: WAITING_TIME }).should(
- 'have.value',
- 'released'
- );
+ page.createReportOfType('Line Chart', barChartCypherQuery);
+ cy.get('main .react-grid-item:eq(2) #x input[name="X-value"]').should('have.value', 'released');
cy.get('main .react-grid-item:eq(2) #value input[name="Y-value"]').should('have.value', 'count');
cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > g').should('have.length', 6);
cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > g:nth-child(2) > line').should(
@@ -136,19 +97,14 @@ describe('NeoDash E2E Tests', () => {
it('creates a map chart report', () => {
cy.checkInitialState();
- createReportOfType('Map', mapChartCypherQuery, true);
- cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > path', { timeout: WAITING_TIME }).should(
- 'have.length',
- 5
- );
+ page.createReportOfType('Map', mapChartCypherQuery, true);
+ cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > path').should('have.length', 5);
});
it('creates a single value report', () => {
cy.checkInitialState();
- createReportOfType('Single Value', barChartCypherQuery);
- cy.get('main .react-grid-item:eq(2) .MuiCardContent-root > div > div:nth-child(2) > span', {
- timeout: WAITING_TIME,
- })
+ page.createReportOfType('Single Value', barChartCypherQuery);
+ cy.get('main .react-grid-item:eq(2) .MuiCardContent-root > div > div:nth-child(2) > span')
.invoke('text')
.then((text) => {
expect(text).to.be.oneOf(['1999', '1,999', '1 999']);
@@ -156,62 +112,49 @@ describe('NeoDash E2E Tests', () => {
});
it.skip('creates a gauge chart report', () => {
- enableAdvancedVisualizations();
+ page.enableAdvancedVisualizations();
cy.checkInitialState();
- createReportOfType('Gauge Chart', gaugeChartCypherQuery);
- cy.get('.text-group > text', { timeout: WAITING_TIME }).contains('69');
+ page.createReportOfType('Gauge Chart', gaugeChartCypherQuery);
+ cy.get('.text-group > text').contains('69');
});
it('creates a sunburst chart report', () => {
- enableAdvancedVisualizations();
+ page.enableAdvancedVisualizations();
cy.checkInitialState();
- createReportOfType('Sunburst Chart', sunburstChartCypherQuery);
- cy.get('main .react-grid-item:eq(2) #index input[name="Path"]', { timeout: WAITING_TIME }).should(
- 'have.value',
- 'x.path'
- );
+ page.createReportOfType('Sunburst Chart', sunburstChartCypherQuery);
+ cy.get('main .react-grid-item:eq(2) #index input[name="Path"]').should('have.value', 'x.path');
cy.get('main .react-grid-item:eq(2) #value input[name="Value"]').should('have.value', 'x.value');
cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > g:nth-child(1) > path').should('have.length', 5);
});
it('creates a circle packing report', () => {
- enableAdvancedVisualizations();
+ page.enableAdvancedVisualizations();
cy.checkInitialState();
- createReportOfType('Circle Packing', sunburstChartCypherQuery);
- cy.get('main .react-grid-item:eq(2) #index input[name="Path"]', { timeout: WAITING_TIME }).should(
- 'have.value',
- 'x.path'
- );
+ page.createReportOfType('Circle Packing', sunburstChartCypherQuery);
+ cy.get('main .react-grid-item:eq(2) #index input[name="Path"]').should('have.value', 'x.path');
cy.get('main .react-grid-item:eq(2) #value input[name="Value"]').should('have.value', 'x.value');
cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > circle').should('have.length', 6);
});
it('creates a tree map report', () => {
- enableAdvancedVisualizations();
+ page.enableAdvancedVisualizations();
cy.checkInitialState();
- createReportOfType('Treemap', sunburstChartCypherQuery);
- cy.get('main .react-grid-item:eq(2) #index input[name="Path"]', { timeout: WAITING_TIME }).should(
- 'have.value',
- 'x.path'
- );
+ page.createReportOfType('Treemap', sunburstChartCypherQuery);
+ cy.get('main .react-grid-item:eq(2) #index input[name="Path"]').should('have.value', 'x.path');
cy.get('main .react-grid-item:eq(2) #value input[name="Value"]').should('have.value', 'x.value');
cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > g').should('have.length', 6);
});
it('creates a sankey chart report', () => {
- enableAdvancedVisualizations();
+ page.enableAdvancedVisualizations();
cy.checkInitialState();
- createReportOfType('Sankey Chart', sankeyChartCypherQuery, true);
- cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > path', { timeout: WAITING_TIME }).should(
- 'have.attr',
- 'fill-opacity',
- 0.5
- );
+ page.createReportOfType('Sankey Chart', sankeyChartCypherQuery, true);
+ cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > path').should('have.attr', 'fill-opacity', 0.5);
});
it('creates a raw json report', () => {
cy.checkInitialState();
- createReportOfType('Raw JSON', barChartCypherQuery);
+ page.createReportOfType('Raw JSON', barChartCypherQuery);
cy.get('main .react-grid-item:eq(2) .MuiCardContent-root textarea:nth-child(1)', { timeout: 45000 }).should(
($div) => {
const text = $div.text();
@@ -222,7 +165,7 @@ describe('NeoDash E2E Tests', () => {
it('creates a parameter select report', () => {
cy.checkInitialState();
- selectReportOfType('Parameter Select');
+ page.selectReportOfType('Parameter Select');
cy.wait(500);
cy.get('#autocomplete-label-type').type('Movie');
cy.get('#autocomplete-label-type-option-0').click();
@@ -236,20 +179,20 @@ describe('NeoDash E2E Tests', () => {
it('creates an iframe report', () => {
cy.checkInitialState();
- createReportOfType('iFrame', iFrameText);
+ page.createReportOfType('iFrame', iFrameText);
cy.get('main .react-grid-item:eq(2) .MuiCardContent-root iframe', { timeout: 45000 }).should('be.visible');
});
it('creates a markdown report', () => {
cy.checkInitialState();
- createReportOfType('Markdown', markdownText);
+ page.createReportOfType('Markdown', markdownText);
cy.get('main .react-grid-item:eq(2) .MuiCardContent-root h1', { timeout: 45000 }).should('have.text', 'Hello');
});
it.skip('creates a form report', () => {
- enableFormsExtension();
+ page.enableFormsExtension();
cy.checkInitialState();
- createReportOfType('Form', formCypherQuery, true, false);
+ page.createReportOfType('Form', formCypherQuery, true, false);
cy.get('main .react-grid-item:eq(2) .form-add-parameter').click();
cy.wait(200);
cy.get('#autocomplete-label-type').type('Movie');
@@ -262,8 +205,10 @@ describe('NeoDash E2E Tests', () => {
cy.get('main .react-grid-item:eq(2) button[aria-label="run"]').scrollIntoView().should('be.visible').click();
cy.wait(500);
+ cy.get('#form-submit').should('be.disabled');
cy.get('#autocomplete').type('The Matrix');
cy.get('#autocomplete-option-0').click();
+ cy.get('#form-submit').should('not.be.disabled');
cy.get('#form-submit').click();
cy.wait(500);
cy.get('.form-submitted-message').should('have.text', 'Form Submitted.Reset Form');
@@ -273,7 +218,7 @@ describe('NeoDash E2E Tests', () => {
// TODO - this test is flaky, especially in GitHub actions environment.
it.skip('test load dashboard from file and stress test report customizations', () => {
try {
- var NUMBER_OF_PAGES_IN_STRESS_TEST_DASHBOARD = 5;
+ const NUMBER_OF_PAGES_IN_STRESS_TEST_DASHBOARD = 5;
const file = cy.request(loadDashboardURL).should((response) => {
cy.get('#root .MuiDrawer-root .MuiIconButton-root:eq(2)').click();
cy.get('.MuiDialog-root .MuiPaper-root .MuiDialogContent-root textarea:eq(0)')
diff --git a/cypress/e2e/utils.js b/cypress/e2e/utils.js
deleted file mode 100644
index ae5639cf9..000000000
--- a/cypress/e2e/utils.js
+++ /dev/null
@@ -1,84 +0,0 @@
-export function enableReportActions() {
- cy.get('main button[aria-label="Extensions').should('be.visible').click();
- cy.get('#checkbox-actions').scrollIntoView();
- cy.get('#checkbox-actions').should('be.visible').click();
- cy.get('.ndl-dialog-close').scrollIntoView().should('be.visible').click();
- cy.wait(200);
-}
-
-export function enableAdvancedVisualizations() {
- cy.get('main button[aria-label="Extensions').should('be.visible').click();
- cy.get('#checkbox-advanced-charts').should('be.visible').click();
- cy.get('.ndl-dialog-close').scrollIntoView().should('be.visible').click();
- cy.wait(200);
-}
-
-export function enableFormsExtension() {
- cy.get('main button[aria-label="Extensions').should('be.visible').click();
- cy.get('#checkbox-forms').scrollIntoView();
- cy.get('#checkbox-forms').should('be.visible').click();
- cy.get('.ndl-dialog-close').scrollIntoView().should('be.visible').click();
- cy.wait(200);
-}
-
-export function selectReportOfType(type) {
- cy.get('main .react-grid-item button[aria-label="add report"]').should('be.visible').click();
- cy.get('main .react-grid-item')
- .contains('No query specified.')
- .parentsUntil('.react-grid-item')
- .find('button[aria-label="settings"]', { timeout: 2000 })
- .should('be.visible')
- .click();
- cy.get('main .react-grid-item:eq(2) #type', { timeout: 2000 }).should('be.visible').click();
- cy.contains(type).click();
- cy.wait(100);
-}
-
-export function createReportOfType(type, query, fast = false, run = true) {
- selectReportOfType(type);
- if (fast) {
- cy.get('main .react-grid-item:eq(2) .ReactCodeMirror').type(query, { delay: 1, parseSpecialCharSequences: false });
- } else {
- cy.get('main .react-grid-item:eq(2) .ReactCodeMirror').type(query, { parseSpecialCharSequences: false });
- }
- cy.wait(400);
-
- if (run) {
- closeSettings('main .react-grid-item:eq(2)');
- }
-}
-
-export function openSettings(cardSelector) {
- cy.get(cardSelector).find('button[aria-label="settings"]', { WAITING_TIME: 2000 }).click();
-}
-
-export function closeSettings(cardSelector) {
- cy.get(`${cardSelector} button[aria-label="run"]`).click();
-}
-
-export function openAdvancedSettings(cardSelector) {
- openSettings(cardSelector);
- cy.get(cardSelector).contains('Advanced settings').click();
-}
-
-export function closeAdvancedSettings(cardSelector) {
- cy.get(cardSelector).contains('Advanced settings').click();
- closeSettings(cardSelector);
-}
-
-export function openReportActionsMenu(cardSelector) {
- openSettings(cardSelector);
- cy.get(cardSelector).find('button[aria-label="custom actions"]').click();
-}
-
-export function updateDropdownAdvancedSetting(cardSelector, settingLabel, targetValue) {
- openAdvancedSettings(cardSelector);
- cy.get(`${cardSelector} .ndl-dropdown`).contains(settingLabel).siblings('div').click();
- cy.contains(targetValue).click();
- closeAdvancedSettings(cardSelector);
-}
-
-export function toggleTableTranspose(cardSelector, enable) {
- let transpose = enable ? 'on' : 'off';
- updateDropdownAdvancedSetting(cardSelector, 'Transpose Rows & Columns', transpose);
-}
diff --git a/cypress/support/index.js b/cypress/index.js
similarity index 95%
rename from cypress/support/index.js
rename to cypress/index.js
index 37a498fb5..cbfe0a766 100644
--- a/cypress/support/index.js
+++ b/cypress/index.js
@@ -14,7 +14,7 @@
// ***********************************************************
// Import commands.js using ES2015 syntax:
-import './commands';
+import './support/commands';
// Alternatively you can use CommonJS syntax:
// require('./commands')
diff --git a/cypress/support/commands.js b/cypress/support/commands.js
index e486473bc..c7e9831e0 100644
--- a/cypress/support/commands.js
+++ b/cypress/support/commands.js
@@ -24,61 +24,29 @@
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
Cypress.Commands.add('getDataTest', (dataTestSelector) => {
- return cy.get(`[data-test="${dataTestSelector}"]`);
- });
-
- /**
- * Function to interact with a specific element and execute additional custom commands.
- * @param {Function} customAction - A callback function containing custom Cypress commands.
- */
-
- // Used to open the 2nd report card and activate 'advanced settings'
- Cypress.Commands.add('advancedSettings', (customAction) => {
- cy.get('.react-grid-layout:eq(0) .MuiGrid-root:eq(1)').within(() => {
- // Opening settings
- cy.get('button').eq(1).click();
- // Activating advanced settings
- cy.get('[role="switch"]').click();
- cy.wait(200);
- customAction();
- });
- });
-
- // Used to open 2nd the report card
- Cypress.Commands.add('openSettings', (customAction) => {
- cy.get('.react-grid-layout:eq(0) .MuiGrid-root:eq(1)').within(() => {
- // Opening settings
- cy.get('button').eq(1).click();
- cy.wait(200);
- customAction();
- });
- });
-
- // Needs to be used when already inside scole of a report card
- Cypress.Commands.add('setDropdownValue', (labelName, setting) => {
- cy.get('.ndl-dropdown')
- .contains('label', labelName)
- .scrollIntoView()
- .should('be.visible')
- .click()
- .type(`${setting}{enter}`);
- });
-
- //Used in start_page.cy.js
- Cypress.Commands.add('checkInitialState', () => {
- // Check the starter cards
- cy.get('main .react-grid-item:eq(0)').should('contain', 'This is your first dashboard!');
- cy.get('main .react-grid-item:eq(1) .force-graph-container canvas').should('be.visible');
- cy.get('main .react-grid-item:eq(2) button').should('have.attr', 'aria-label', 'add report');
- });
-
- // Creates a card
- const WAITING_TIME = 20000;
- Cypress.Commands.add('createCard', () => {
- // Check the starter cards
- cy.get('main .react-grid-item button[aria-label="add report"]', { timeout: WAITING_TIME })
- .should('be.visible')
- .click();
- cy.wait(1000);
- cy.get('main .react-grid-item:eq(2)').should('contain', 'No query specified.');
- });
\ No newline at end of file
+ return cy.get(`[data-test="${dataTestSelector}"]`);
+});
+
+/**
+ * Function to interact with a specific element and execute additional custom commands.
+ * @param {Function} customAction - A callback function containing custom Cypress commands.
+ */
+
+//Used in start_page.cy.js
+Cypress.Commands.add('checkInitialState', () => {
+ // Check the starter cards
+ cy.get('main .react-grid-item:eq(0)').should('contain', 'This is your first dashboard!');
+ cy.get('main .react-grid-item:eq(1) .force-graph-container canvas').should('be.visible');
+ cy.get('main .react-grid-item:eq(2) button').should('have.attr', 'aria-label', 'add report');
+});
+
+// Creates a card
+const WAITING_TIME = 20000;
+Cypress.Commands.add('createCard', () => {
+ // Check the starter cards
+ cy.get('main .react-grid-item button[aria-label="add report"]', { timeout: WAITING_TIME })
+ .should('be.visible')
+ .click();
+ cy.wait(1000);
+ cy.get('main .react-grid-item:eq(2)').should('contain', 'No query specified.');
+});
diff --git a/docs/modules/ROOT/pages/banner.adoc b/docs/modules/ROOT/pages/banner.adoc
new file mode 100644
index 000000000..fdb12c826
--- /dev/null
+++ b/docs/modules/ROOT/pages/banner.adoc
@@ -0,0 +1,6 @@
+[NOTE]
+====
+This documentation pertains to the unsupported version of NeoDash, as part of Neo4j Labs.
+For users of the supported NeoDash offering, refer to https://neo4j.com/docs/neodash-commercial/[NeoDash commercial].
+
+====
\ No newline at end of file
diff --git a/docs/modules/ROOT/pages/developer-guide/adding-visualizations.adoc b/docs/modules/ROOT/pages/developer-guide/adding-visualizations.adoc
index dc47ee4ab..4d9fd76eb 100644
--- a/docs/modules/ROOT/pages/developer-guide/adding-visualizations.adoc
+++ b/docs/modules/ROOT/pages/developer-guide/adding-visualizations.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Adding Visualizations
You can extend NeoDash with your own visualizations without diving deep
diff --git a/docs/modules/ROOT/pages/developer-guide/build-and-run.adoc b/docs/modules/ROOT/pages/developer-guide/build-and-run.adoc
index 45cbc2641..f52b88fb5 100644
--- a/docs/modules/ROOT/pages/developer-guide/build-and-run.adoc
+++ b/docs/modules/ROOT/pages/developer-guide/build-and-run.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Build & Run
To start developing the application, you will need to set up the
@@ -76,7 +78,9 @@ docker run -it –rm -p 5005:5005 neodash
== Run on Kubernetes
-An example of a pod definition YAML file to create a NeoDash pod in a cluster:
+=== To deploy using YAML files
+
+YAML examples are available in the https://github.com/neo4j-labs/neodash[NeoDash repository]. Here is an example of a pod definition YAML file to create a NeoDash pod in a cluster:
....
apiVersion: v1
@@ -108,3 +112,118 @@ spec:
selector:
project: neodash
....
+
+=== To deploy using a Helm Charts
+
+A Kubernetes Helm chart is available in the https://github.com/neo4j-labs/neodash[the NeoDash repository] and here is the full example of the Helm chart values.yaml file,
+
+....
+# Name override or full name override
+nameOverride: ''
+fullnameOverride: neodash-test
+
+# Number of pods
+replicaCount: 1
+
+# Image Details
+image:
+ repository: neo4jlabs/neodash
+ pullPolicy: IfNotPresent
+ tag: 'latest'
+imagePullSecrets: [] # Image pull secret if any
+
+# Pod annotations, labels and security context
+podAnnotations: {}
+podLabels: {}
+podSecurityContext: {}
+
+# Mode configuration using environment variables
+# Set reader mode environment variables when enable_reader_mode is true
+enable_reader_mode: true
+env:
+ - name: "ssoEnabled"
+ value: "false"
+ - name: "standalone"
+ value: "true"
+ - name: "standaloneProtocol"
+ value: "neo4j+s"
+ - name: "standaloneHost"
+ value: "localhost"
+ - name: "standalonePort"
+ value: "7687"
+ - name: "standaloneDatabase"
+ value: neo4j
+ - name: "standaloneDashboardName"
+ value: "test"
+ - name: "standaloneDashboardDatabase"
+ value: neo4j
+ - name: "standaloneAllowLoad"
+ value: "false"
+ - name: "standaloneLoadFromOtherDatabases"
+ value: "false"
+ - name: "standaloneMultiDatabase"
+ value: "false"
+
+# Environment variable from secret
+envFromSecrets: []
+ # standaloneUsername:
+ # secretName: "neo4j-connection-secrets"
+ # key: "username"
+ # standalonePassword:
+ # secretName: "neo4j-connection-secrets"
+ # key: "password"
+
+# Service details
+service:
+ type: LoadBalancer # Can also be ClusterIP or NodePort
+ port: 5005 # For the service to listen in for Traffic
+ targetPort: 5005 # Target port is the container port
+ annotations: {} # Service annotations for the LoadBalance
+
+# Ingress
+ingress:
+ enabled: false # Enable Kubernetes Ingress
+ className: 'alb' # Class Name
+ annotations: {} # Cloud LoadBalancer annotations
+ hosts: []
+ # - host: neodash.example.com
+ # paths:
+ # - path: '/'
+ # pathType: Prefix
+ tls: []
+
+# Pod resources request, limits and health check
+resources:
+ requests:
+ memory: "64Mi"
+ cpu: "250m"
+ limits:
+ memory: "128Mi"
+ cpu: "500m"
+livenessProbe:
+ httpGet:
+ path: /*
+ port: 5005
+readinessProbe:
+ httpGet:
+ path: /*
+ port: 5005
+
+# Pod Autoscaler
+autoscaling:
+ enabled: false
+ # minReplicas: 1
+ # maxReplicas: 100
+ # targetCPUUtilizationPercentage: 80
+
+# Pod Volumes
+volumes: []
+volumeMounts: []
+
+# Service Account
+serviceAccount:
+ create: true
+ automount: true
+ # annotations: {}
+ # name: ''
+....
\ No newline at end of file
diff --git a/docs/modules/ROOT/pages/developer-guide/component-overview.adoc b/docs/modules/ROOT/pages/developer-guide/component-overview.adoc
index e02da7989..27d78236d 100644
--- a/docs/modules/ROOT/pages/developer-guide/component-overview.adoc
+++ b/docs/modules/ROOT/pages/developer-guide/component-overview.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Component Overview
diff --git a/docs/modules/ROOT/pages/developer-guide/configuration.adoc b/docs/modules/ROOT/pages/developer-guide/configuration.adoc
index 604ed1298..cca62fdbd 100644
--- a/docs/modules/ROOT/pages/developer-guide/configuration.adoc
+++ b/docs/modules/ROOT/pages/developer-guide/configuration.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Configuration
When using a custom NeoDash deployment, there are several settings that
@@ -133,7 +135,7 @@ must be granted to enble any user to create logs.
⚠️ * Load/Save from/to file are not logged (only from/to Database)
-|loggingDatabase |string |neo4j |When loggingMode is set to anything
+|loggingDatabase |string |logs |When loggingMode is set to anything
else than '0', the database to use for logging. Log records (nodes)
will be created in this database.
diff --git a/docs/modules/ROOT/pages/developer-guide/contributing.adoc b/docs/modules/ROOT/pages/developer-guide/contributing.adoc
index 1cb695dde..90c198ff9 100644
--- a/docs/modules/ROOT/pages/developer-guide/contributing.adoc
+++ b/docs/modules/ROOT/pages/developer-guide/contributing.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Contributing
Contributions to the project are highly welcomed. Please consider
diff --git a/docs/modules/ROOT/pages/developer-guide/deploy-a-build.adoc b/docs/modules/ROOT/pages/developer-guide/deploy-a-build.adoc
index a5f2fd529..5646b89ad 100644
--- a/docs/modules/ROOT/pages/developer-guide/deploy-a-build.adoc
+++ b/docs/modules/ROOT/pages/developer-guide/deploy-a-build.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Deploy a Build
If you have a pre-built NeoDash application, you can easily deploy it on an any webserver.
A NeoDash build is "just" a collection of HTML, CSS and JavaScript files, so it can run virtually anywhere.
@@ -37,7 +39,7 @@ Depending on the webserver type and version, this could be different directory.
As an example - to copy the files to an nginx webserver using `scp`:
```bash
-scp neodash-2.4.8 username@host:/usr/share/nginx/html
+scp neodash-2.4.9-labs username@host:/usr/share/nginx/html
```
NeoDash should now be visible by visiting your (sub)domain in the browser.
diff --git a/docs/modules/ROOT/pages/developer-guide/design.adoc b/docs/modules/ROOT/pages/developer-guide/design.adoc
index 5f498bb2d..3c7bd32eb 100644
--- a/docs/modules/ROOT/pages/developer-guide/design.adoc
+++ b/docs/modules/ROOT/pages/developer-guide/design.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Design
This page contains some key guidelines for design of the application.
diff --git a/docs/modules/ROOT/pages/developer-guide/index.adoc b/docs/modules/ROOT/pages/developer-guide/index.adoc
index f4538d764..b9424ebb0 100644
--- a/docs/modules/ROOT/pages/developer-guide/index.adoc
+++ b/docs/modules/ROOT/pages/developer-guide/index.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Developer Guide
This guide contains information for developers looking to deploy NeoDash, or extend it for their own needs.
diff --git a/docs/modules/ROOT/pages/developer-guide/session-storage.adoc b/docs/modules/ROOT/pages/developer-guide/session-storage.adoc
index a4861a4cf..7a668e4a7 100644
--- a/docs/modules/ROOT/pages/developer-guide/session-storage.adoc
+++ b/docs/modules/ROOT/pages/developer-guide/session-storage.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Session Storage
This reducer serves only to store data that we want to reset at each new session.
diff --git a/docs/modules/ROOT/pages/developer-guide/standalone-mode.adoc b/docs/modules/ROOT/pages/developer-guide/standalone-mode.adoc
index f752cbad1..58575256e 100644
--- a/docs/modules/ROOT/pages/developer-guide/standalone-mode.adoc
+++ b/docs/modules/ROOT/pages/developer-guide/standalone-mode.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Standalone Mode
Next to being a dashboard editor, NeoDash can be deployed in a
diff --git a/docs/modules/ROOT/pages/developer-guide/state-management.adoc b/docs/modules/ROOT/pages/developer-guide/state-management.adoc
index bdece9b9e..1083bf2c1 100644
--- a/docs/modules/ROOT/pages/developer-guide/state-management.adoc
+++ b/docs/modules/ROOT/pages/developer-guide/state-management.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= State Management
NeoDash is an application with a complex internal state. If you are
diff --git a/docs/modules/ROOT/pages/developer-guide/style-configuration.adoc b/docs/modules/ROOT/pages/developer-guide/style-configuration.adoc
index b82124d2f..4d5495a91 100644
--- a/docs/modules/ROOT/pages/developer-guide/style-configuration.adoc
+++ b/docs/modules/ROOT/pages/developer-guide/style-configuration.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Style Configuration
When using a custom NeoDash deployment, there are several theme variables that
@@ -14,7 +16,7 @@ docker run -p 5005:5005 \
-e DASHBOARD_HEADER_BRAND_LOGO=https://picsum.photos/500/100 \
neo4jlabs/neodash
....
-
+
An example configuration for NeoDash
....
diff --git a/docs/modules/ROOT/pages/developer-guide/testing.adoc b/docs/modules/ROOT/pages/developer-guide/testing.adoc
index 402ed1bca..5c492a375 100644
--- a/docs/modules/ROOT/pages/developer-guide/testing.adoc
+++ b/docs/modules/ROOT/pages/developer-guide/testing.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Testing
NeoDash uses *Cypress* for automated testing. To install Cypress, check
diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc
index 6c7816dce..83eadebd0 100644
--- a/docs/modules/ROOT/pages/index.adoc
+++ b/docs/modules/ROOT/pages/index.adoc
@@ -1,3 +1,5 @@
+include::/banner.adoc[]
+
= Introduction
This portal contains information on getting started with NeoDash - A Low-Code Dashboard Builder for Neo4j.
diff --git a/docs/modules/ROOT/pages/quickstart.adoc b/docs/modules/ROOT/pages/quickstart.adoc
index b128dac71..4ae165058 100644
--- a/docs/modules/ROOT/pages/quickstart.adoc
+++ b/docs/modules/ROOT/pages/quickstart.adoc
@@ -1,3 +1,5 @@
+include::/banner.adoc[]
+
= Quickstart
There are three easy ways to run NeoDash and start dashboarding your Neo4j data:
diff --git a/docs/modules/ROOT/pages/user-guide/access-control.adoc b/docs/modules/ROOT/pages/user-guide/access-control.adoc
index 03c62dfd1..47cf3da31 100644
--- a/docs/modules/ROOT/pages/user-guide/access-control.adoc
+++ b/docs/modules/ROOT/pages/user-guide/access-control.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Access Control
The Access Control feature in NeoDash is a security measure that allows Users with write access or higher privileges to manage who has access to specific dashboards.
diff --git a/docs/modules/ROOT/pages/user-guide/bloom-integration.adoc b/docs/modules/ROOT/pages/user-guide/bloom-integration.adoc
index 8acdc4e92..09dcce58c 100644
--- a/docs/modules/ROOT/pages/user-guide/bloom-integration.adoc
+++ b/docs/modules/ROOT/pages/user-guide/bloom-integration.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Bloom Integration
NeoDash can be linked to Neo4j Bloom perspectives by using
diff --git a/docs/modules/ROOT/pages/user-guide/dashboards.adoc b/docs/modules/ROOT/pages/user-guide/dashboards.adoc
index dc6b70571..d0aa53b11 100644
--- a/docs/modules/ROOT/pages/user-guide/dashboards.adoc
+++ b/docs/modules/ROOT/pages/user-guide/dashboards.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Dashboards
In NeoDash, a dashboard consists of several pages, each of which can
diff --git a/docs/modules/ROOT/pages/user-guide/extensions/access-control-management.adoc b/docs/modules/ROOT/pages/user-guide/extensions/access-control-management.adoc
index 941b4dbda..9a6219c45 100644
--- a/docs/modules/ROOT/pages/user-guide/extensions/access-control-management.adoc
+++ b/docs/modules/ROOT/pages/user-guide/extensions/access-control-management.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Access Control Management
This extension lets you manage access control for roles and users, letting you assign users to roles as well as controlling which node labels can be read by a user.
diff --git a/docs/modules/ROOT/pages/user-guide/extensions/advanced-visualizations.adoc b/docs/modules/ROOT/pages/user-guide/extensions/advanced-visualizations.adoc
index fb02c5a94..f4e7e8e98 100644
--- a/docs/modules/ROOT/pages/user-guide/extensions/advanced-visualizations.adoc
+++ b/docs/modules/ROOT/pages/user-guide/extensions/advanced-visualizations.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Advanced Visualizations
Advanced visualizations let you extend your dashboard with complex, powerful visualizations beyond the standard visualizations.
diff --git a/docs/modules/ROOT/pages/user-guide/extensions/forms.adoc b/docs/modules/ROOT/pages/user-guide/extensions/forms.adoc
index 4bce11d4d..3ea8c965e 100644
--- a/docs/modules/ROOT/pages/user-guide/extensions/forms.adoc
+++ b/docs/modules/ROOT/pages/user-guide/extensions/forms.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Forms
The 'forms' extension lets you combine different parameter selectors to update / modify your graph data.
diff --git a/docs/modules/ROOT/pages/user-guide/extensions/index.adoc b/docs/modules/ROOT/pages/user-guide/extensions/index.adoc
index f267315ff..6d16b1700 100644
--- a/docs/modules/ROOT/pages/user-guide/extensions/index.adoc
+++ b/docs/modules/ROOT/pages/user-guide/extensions/index.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Extensions
Extensions provide a way to expand the basic functionality of NeoDash with extra features.
diff --git a/docs/modules/ROOT/pages/user-guide/extensions/natural-language-queries.adoc b/docs/modules/ROOT/pages/user-guide/extensions/natural-language-queries.adoc
index e7f9ea059..675a00a2d 100644
--- a/docs/modules/ROOT/pages/user-guide/extensions/natural-language-queries.adoc
+++ b/docs/modules/ROOT/pages/user-guide/extensions/natural-language-queries.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Text2Cypher - Natural Language Queries
Use natural language to generate Cypher queries in NeoDash. Connect to an LLM through an API, and let NeoDash use your database schema + the report types to generate queries automatically.
diff --git a/docs/modules/ROOT/pages/user-guide/extensions/report-actions.adoc b/docs/modules/ROOT/pages/user-guide/extensions/report-actions.adoc
index 8b50f1651..a381c0076 100644
--- a/docs/modules/ROOT/pages/user-guide/extensions/report-actions.adoc
+++ b/docs/modules/ROOT/pages/user-guide/extensions/report-actions.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Report Actions
link:../#_2_pro_extensions[label:Pro Extension[]]
diff --git a/docs/modules/ROOT/pages/user-guide/extensions/rule-based-styling.adoc b/docs/modules/ROOT/pages/user-guide/extensions/rule-based-styling.adoc
index ee6adc4ca..8a4b0ea9c 100644
--- a/docs/modules/ROOT/pages/user-guide/extensions/rule-based-styling.adoc
+++ b/docs/modules/ROOT/pages/user-guide/extensions/rule-based-styling.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Rule-Based Styling
diff --git a/docs/modules/ROOT/pages/user-guide/extensions/workflows.adoc b/docs/modules/ROOT/pages/user-guide/extensions/workflows.adoc
index 2b95b06d5..a735dbc2c 100644
--- a/docs/modules/ROOT/pages/user-guide/extensions/workflows.adoc
+++ b/docs/modules/ROOT/pages/user-guide/extensions/workflows.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Workflows
Introducing an advanced extension for creating, managing, and running workflows with Cypher queries. Simplify ETL flows, execute complex query chains, and run graph data science workloads effortlessly from Neodash.
diff --git a/docs/modules/ROOT/pages/user-guide/faq.adoc b/docs/modules/ROOT/pages/user-guide/faq.adoc
index cdd5efaad..08ece7dd1 100644
--- a/docs/modules/ROOT/pages/user-guide/faq.adoc
+++ b/docs/modules/ROOT/pages/user-guide/faq.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= FAQ
== 1. How can I learn more about NeoDash?
diff --git a/docs/modules/ROOT/pages/user-guide/index.adoc b/docs/modules/ROOT/pages/user-guide/index.adoc
index dde9d9e05..d87dffb6d 100644
--- a/docs/modules/ROOT/pages/user-guide/index.adoc
+++ b/docs/modules/ROOT/pages/user-guide/index.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= User Guide
The following pages contain everything you need to get started with NeoDash.
diff --git a/docs/modules/ROOT/pages/user-guide/pages.adoc b/docs/modules/ROOT/pages/user-guide/pages.adoc
index b332e4ae7..0d01f37d4 100644
--- a/docs/modules/ROOT/pages/user-guide/pages.adoc
+++ b/docs/modules/ROOT/pages/user-guide/pages.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Pages
A page is a collection of link:../reports[reports] that can be viewed at
diff --git a/docs/modules/ROOT/pages/user-guide/publishing.adoc b/docs/modules/ROOT/pages/user-guide/publishing.adoc
index 2b1015a03..8fe77739c 100644
--- a/docs/modules/ROOT/pages/user-guide/publishing.adoc
+++ b/docs/modules/ROOT/pages/user-guide/publishing.adoc
@@ -1,3 +1,5 @@
+include::../banner.adoc[]
+
= Publishing
When you are done building a dashboard, you may want to *publish* that
diff --git a/docs/modules/ROOT/pages/user-guide/reports/areamap.adoc b/docs/modules/ROOT/pages/user-guide/reports/areamap.adoc
index d28f4c6bc..9d3c4a79e 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/areamap.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/areamap.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Area Map
link:../../extensions/advanced-visualizations[label:Advanced Visualization[]]
diff --git a/docs/modules/ROOT/pages/user-guide/reports/bar-chart.adoc b/docs/modules/ROOT/pages/user-guide/reports/bar-chart.adoc
index 56a8773c1..6a280c750 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/bar-chart.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/bar-chart.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Bar Chart
A bar chart will draw categories and values in a familiar bar-layout.
diff --git a/docs/modules/ROOT/pages/user-guide/reports/choropleth.adoc b/docs/modules/ROOT/pages/user-guide/reports/choropleth.adoc
index 35fdbdd19..8cfd6037c 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/choropleth.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/choropleth.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Choropleth
link:../../extensions/advanced-visualizations[label:Advanced Visualization[]]
diff --git a/docs/modules/ROOT/pages/user-guide/reports/circle-packing.adoc b/docs/modules/ROOT/pages/user-guide/reports/circle-packing.adoc
index 61146b24d..cab5079bd 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/circle-packing.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/circle-packing.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Circle Packing
link:../../extensions/advanced-visualizations[label:Advanced Visualization[]]
diff --git a/docs/modules/ROOT/pages/user-guide/reports/form.adoc b/docs/modules/ROOT/pages/user-guide/reports/form.adoc
index d7817f171..f10776561 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/form.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/form.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Form
A form is a special type of report that lets users run predefined, parameterized queries.
diff --git a/docs/modules/ROOT/pages/user-guide/reports/gantt.adoc b/docs/modules/ROOT/pages/user-guide/reports/gantt.adoc
index c54567aa5..0332fdd04 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/gantt.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/gantt.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Gantt Chart
link:../../extensions/advanced-visualizations[label:Advanced Visualization[]]
diff --git a/docs/modules/ROOT/pages/user-guide/reports/gauge-chart.adoc b/docs/modules/ROOT/pages/user-guide/reports/gauge-chart.adoc
index 067acd6aa..41ed80eba 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/gauge-chart.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/gauge-chart.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Gauge Chart
link:../../extensions/advanced-visualizations[label:Advanced Visualization[]]
diff --git a/docs/modules/ROOT/pages/user-guide/reports/graph.adoc b/docs/modules/ROOT/pages/user-guide/reports/graph.adoc
index 4d18523dd..8638ac9e6 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/graph.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/graph.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Graph
The graph report will render all returned nodes, relationships and paths
diff --git a/docs/modules/ROOT/pages/user-guide/reports/graph3d.adoc b/docs/modules/ROOT/pages/user-guide/reports/graph3d.adoc
index 31d2ef6a2..d2ddeb9dc 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/graph3d.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/graph3d.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= 3D Graph
link:../../extensions/advanced-visualizations[label:Advanced Visualization[]]
diff --git a/docs/modules/ROOT/pages/user-guide/reports/iframe.adoc b/docs/modules/ROOT/pages/user-guide/reports/iframe.adoc
index 44e822e08..8f0fb9598 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/iframe.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/iframe.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= iFrame
An iFrame report lets you embed a webpage inside your NeoDash dashboard.
diff --git a/docs/modules/ROOT/pages/user-guide/reports/index.adoc b/docs/modules/ROOT/pages/user-guide/reports/index.adoc
index da44ed606..d05324060 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/index.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/index.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Reports
A report is the smallest building build of your dashboard. Each report
diff --git a/docs/modules/ROOT/pages/user-guide/reports/line-chart.adoc b/docs/modules/ROOT/pages/user-guide/reports/line-chart.adoc
index ec0c21d52..56adcd965 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/line-chart.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/line-chart.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Line Chart
A line chart can be used to draw one or more lines in a two-dimensional
diff --git a/docs/modules/ROOT/pages/user-guide/reports/map.adoc b/docs/modules/ROOT/pages/user-guide/reports/map.adoc
index 081b917f2..4779c3c98 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/map.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/map.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Map
The map report will render all returned nodes, relationships and paths
diff --git a/docs/modules/ROOT/pages/user-guide/reports/markdown.adoc b/docs/modules/ROOT/pages/user-guide/reports/markdown.adoc
index fc09c3726..85d19cec6 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/markdown.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/markdown.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Markdown
Markdown reports let you specify
diff --git a/docs/modules/ROOT/pages/user-guide/reports/parameter-select.adoc b/docs/modules/ROOT/pages/user-guide/reports/parameter-select.adoc
index 2951b7133..cfa09b69a 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/parameter-select.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/parameter-select.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Parameter Select
Parameter select reports provide you with an easy way to add
interactivity into your dashboards.
diff --git a/docs/modules/ROOT/pages/user-guide/reports/pie-chart.adoc b/docs/modules/ROOT/pages/user-guide/reports/pie-chart.adoc
index 9300388a7..f4ad133b5 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/pie-chart.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/pie-chart.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Pie Chart
A pie chart will draw categories and values in a circular disc layout.
diff --git a/docs/modules/ROOT/pages/user-guide/reports/radar.adoc b/docs/modules/ROOT/pages/user-guide/reports/radar.adoc
index 4cd805e22..e6a4bcaf6 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/radar.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/radar.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Radar Chart
link:../../extensions/advanced-visualizations[label:Advanced Visualization[]]
diff --git a/docs/modules/ROOT/pages/user-guide/reports/raw-json.adoc b/docs/modules/ROOT/pages/user-guide/reports/raw-json.adoc
index cf523529e..ec9725e83 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/raw-json.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/raw-json.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Raw JSON
The Raw JSON report renders the JSON response received from Neo4j
diff --git a/docs/modules/ROOT/pages/user-guide/reports/sankey.adoc b/docs/modules/ROOT/pages/user-guide/reports/sankey.adoc
index f725d2d3e..22d014803 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/sankey.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/sankey.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Sankey Chart
link:../../extensions/advanced-visualizations[label:Advanced Visualization[]]
diff --git a/docs/modules/ROOT/pages/user-guide/reports/single-value.adoc b/docs/modules/ROOT/pages/user-guide/reports/single-value.adoc
index 593f92a11..f5a2f99c7 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/single-value.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/single-value.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Single Value
A single value report will render the first column of the first row
diff --git a/docs/modules/ROOT/pages/user-guide/reports/sunburst.adoc b/docs/modules/ROOT/pages/user-guide/reports/sunburst.adoc
index c3385bcdc..6f17c7541 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/sunburst.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/sunburst.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Sunburst
link:../../extensions/advanced-visualizations[label:Advanced Visualization[]]
diff --git a/docs/modules/ROOT/pages/user-guide/reports/table.adoc b/docs/modules/ROOT/pages/user-guide/reports/table.adoc
index 8bb11cb14..8b352f2c2 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/table.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/table.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Table
The most common report in a dashboard is often a simple table view.
diff --git a/docs/modules/ROOT/pages/user-guide/reports/treemap.adoc b/docs/modules/ROOT/pages/user-guide/reports/treemap.adoc
index 9a07ec12a..a8e620060 100644
--- a/docs/modules/ROOT/pages/user-guide/reports/treemap.adoc
+++ b/docs/modules/ROOT/pages/user-guide/reports/treemap.adoc
@@ -1,3 +1,5 @@
+include::../../banner.adoc[]
+
= Treemap
link:../../extensions/advanced-visualizations[label:Advanced Visualization[]]
diff --git a/docs/package-lock.json b/docs/package-lock.json
index 994e25648..6f4bd14e6 100644
--- a/docs/package-lock.json
+++ b/docs/package-lock.json
@@ -420,20 +420,20 @@
}
},
"node_modules/body-parser": {
- "version": "1.20.0",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
- "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
+ "version": "1.20.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
+ "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"dependencies": {
"bytes": "3.1.2",
- "content-type": "~1.0.4",
+ "content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
- "qs": "6.10.3",
- "raw-body": "2.5.1",
+ "qs": "6.11.0",
+ "raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
@@ -521,12 +521,18 @@
}
},
"node_modules/call-bind": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
- "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"dependencies": {
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.0.2"
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -662,9 +668,9 @@
}
},
"node_modules/content-type": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"engines": {
"node": ">= 0.6"
}
@@ -695,9 +701,9 @@
}
},
"node_modules/cookie": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
- "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"engines": {
"node": ">= 0.6"
}
@@ -753,6 +759,22 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/define-properties": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
@@ -822,6 +844,25 @@
"once": "^1.4.0"
}
},
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -852,16 +893,16 @@
}
},
"node_modules/express": {
- "version": "4.18.1",
- "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
- "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
+ "version": "4.19.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
+ "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
- "body-parser": "1.20.0",
+ "body-parser": "1.20.2",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
- "cookie": "0.5.0",
+ "cookie": "0.6.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
@@ -877,7 +918,7 @@
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"proxy-addr": "~2.0.7",
- "qs": "6.10.3",
+ "qs": "6.11.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.18.0",
@@ -1034,18 +1075,26 @@
}
},
"node_modules/function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
},
"node_modules/get-intrinsic": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
- "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"dependencies": {
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.3"
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -1137,6 +1186,17 @@
"node": ">=10.13.0"
}
},
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/graceful-fs": {
"version": "4.2.10",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
@@ -1179,17 +1239,6 @@
"uglify-js": "^3.1.4"
}
},
- "node_modules/has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dependencies": {
- "function-bind": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4.0"
- }
- },
"node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -1199,11 +1248,22 @@
}
},
"node_modules/has-property-descriptors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
- "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dependencies": {
- "get-intrinsic": "^1.1.1"
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+ "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -1220,6 +1280,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/help-me": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/help-me/-/help-me-4.1.0.tgz",
@@ -1776,9 +1847,9 @@
}
},
"node_modules/object-inspect": {
- "version": "1.12.2",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
- "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
+ "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -2083,9 +2154,9 @@
}
},
"node_modules/qs": {
- "version": "6.10.3",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
- "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
+ "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
"dependencies": {
"side-channel": "^1.0.4"
},
@@ -2118,9 +2189,9 @@
}
},
"node_modules/raw-body": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
- "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
@@ -2307,6 +2378,22 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -2330,13 +2417,17 @@
"integrity": "sha512-RPQhIndEIVUCjkfkQ6rs6sOR6pkxJWCNdxtfG5pP0RVgUYbK5911kLTF0TNcCC0G3YCGd492rMollFT2aTd9iQ=="
},
"node_modules/side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+ "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"dependencies": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -3178,20 +3269,20 @@
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
},
"body-parser": {
- "version": "1.20.0",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
- "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
+ "version": "1.20.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
+ "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"requires": {
"bytes": "3.1.2",
- "content-type": "~1.0.4",
+ "content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
- "qs": "6.10.3",
- "raw-body": "2.5.1",
+ "qs": "6.11.0",
+ "raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
}
@@ -3246,12 +3337,15 @@
}
},
"call-bind": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
- "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"requires": {
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.0.2"
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
}
},
"chokidar": {
@@ -3362,9 +3456,9 @@
}
},
"content-type": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="
},
"convert-source-map": {
"version": "1.8.0",
@@ -3391,9 +3485,9 @@
}
},
"cookie": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
- "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="
},
"cookie-signature": {
"version": "1.0.6",
@@ -3431,6 +3525,16 @@
"mimic-response": "^3.1.0"
}
},
+ "define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "requires": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ }
+ },
"define-properties": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
@@ -3484,6 +3588,19 @@
"once": "^1.4.0"
}
},
+ "es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "requires": {
+ "get-intrinsic": "^1.2.4"
+ }
+ },
+ "es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="
+ },
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -3505,16 +3622,16 @@
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="
},
"express": {
- "version": "4.18.1",
- "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
- "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
+ "version": "4.19.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
+ "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
"requires": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
- "body-parser": "1.20.0",
+ "body-parser": "1.20.2",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
- "cookie": "0.5.0",
+ "cookie": "0.6.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
@@ -3530,7 +3647,7 @@
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"proxy-addr": "~2.0.7",
- "qs": "6.10.3",
+ "qs": "6.11.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.18.0",
@@ -3661,18 +3778,20 @@
"optional": true
},
"function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
},
"get-intrinsic": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
- "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"requires": {
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.3"
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
}
},
"glob": {
@@ -3747,6 +3866,14 @@
}
}
},
+ "gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "requires": {
+ "get-intrinsic": "^1.1.3"
+ }
+ },
"graceful-fs": {
"version": "4.2.10",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
@@ -3778,32 +3905,37 @@
"wordwrap": "^1.0.0"
}
},
- "has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "requires": {
- "function-bind": "^1.1.1"
- }
- },
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
},
"has-property-descriptors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
- "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"requires": {
- "get-intrinsic": "^1.1.1"
+ "es-define-property": "^1.0.0"
}
},
+ "has-proto": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+ "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q=="
+ },
"has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
},
+ "hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "requires": {
+ "function-bind": "^1.1.2"
+ }
+ },
"help-me": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/help-me/-/help-me-4.1.0.tgz",
@@ -4222,9 +4354,9 @@
}
},
"object-inspect": {
- "version": "1.12.2",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
- "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ=="
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
+ "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ=="
},
"object-keys": {
"version": "1.1.1",
@@ -4478,9 +4610,9 @@
}
},
"qs": {
- "version": "6.10.3",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
- "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
+ "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
"requires": {
"side-channel": "^1.0.4"
}
@@ -4504,9 +4636,9 @@
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
},
"raw-body": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
- "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"requires": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
@@ -4642,6 +4774,19 @@
"send": "0.18.0"
}
},
+ "set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "requires": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ }
+ },
"setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -4662,13 +4807,14 @@
"integrity": "sha512-RPQhIndEIVUCjkfkQ6rs6sOR6pkxJWCNdxtfG5pP0RVgUYbK5911kLTF0TNcCC0G3YCGd492rMollFT2aTd9iQ=="
},
"side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+ "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"requires": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
}
},
"simple-concat": {
diff --git a/docs/yarn.lock b/docs/yarn.lock
index 8c2a976bd..5f4adab6a 100644
--- a/docs/yarn.lock
+++ b/docs/yarn.lock
@@ -285,13 +285,13 @@ binary-extensions@^2.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
-body-parser@1.20.1:
- version "1.20.1"
- resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
- integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==
+body-parser@1.20.2:
+ version "1.20.2"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
+ integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==
dependencies:
bytes "3.1.2"
- content-type "~1.0.4"
+ content-type "~1.0.5"
debug "2.6.9"
depd "2.0.0"
destroy "1.2.0"
@@ -299,7 +299,7 @@ body-parser@1.20.1:
iconv-lite "0.4.24"
on-finished "2.4.1"
qs "6.11.0"
- raw-body "2.5.1"
+ raw-body "2.5.2"
type-is "~1.6.18"
unpipe "1.0.0"
@@ -429,10 +429,10 @@ content-disposition@0.5.4:
dependencies:
safe-buffer "5.2.1"
-content-type@~1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
- integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
+content-type@~1.0.4, content-type@~1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
+ integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
convert-source-map@^1.5.0:
version "1.9.0"
@@ -452,10 +452,10 @@ cookie-signature@1.0.6:
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
-cookie@0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
- integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
+cookie@0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
+ integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
core-util-is@~1.0.0:
version "1.0.3"
@@ -574,16 +574,16 @@ events@^3.3.0:
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
express@^4.17.1:
- version "4.18.2"
- resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
- integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
+ version "4.19.2"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465"
+ integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==
dependencies:
accepts "~1.3.8"
array-flatten "1.1.1"
- body-parser "1.20.1"
+ body-parser "1.20.2"
content-disposition "0.5.4"
content-type "~1.0.4"
- cookie "0.5.0"
+ cookie "0.6.0"
cookie-signature "1.0.6"
debug "2.6.9"
depd "2.0.0"
@@ -1420,10 +1420,10 @@ range-parser@~1.2.1:
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
-raw-body@2.5.1:
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
- integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
+raw-body@2.5.2:
+ version "2.5.2"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a"
+ integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==
dependencies:
bytes "3.1.2"
http-errors "2.0.0"
diff --git a/evolving.png b/evolving.png
new file mode 100644
index 000000000..ebc85364b
Binary files /dev/null and b/evolving.png differ
diff --git a/gallery/yarn.lock b/gallery/yarn.lock
index 0483d3743..aa9a0cde5 100644
--- a/gallery/yarn.lock
+++ b/gallery/yarn.lock
@@ -2994,13 +2994,13 @@ bluebird@^3.5.5:
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
-body-parser@1.20.1:
- version "1.20.1"
- resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
- integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==
+body-parser@1.20.2:
+ version "1.20.2"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
+ integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==
dependencies:
bytes "3.1.2"
- content-type "~1.0.4"
+ content-type "~1.0.5"
debug "2.6.9"
depd "2.0.0"
destroy "1.2.0"
@@ -3008,7 +3008,7 @@ body-parser@1.20.1:
iconv-lite "0.4.24"
on-finished "2.4.1"
qs "6.11.0"
- raw-body "2.5.1"
+ raw-body "2.5.2"
type-is "~1.6.18"
unpipe "1.0.0"
@@ -3042,12 +3042,19 @@ brace-expansion@^2.0.1:
dependencies:
balanced-match "^1.0.0"
-braces@^3.0.2, braces@~3.0.2:
+braces@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
+ integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
+ dependencies:
+ fill-range "^7.1.1"
+
+braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
dependencies:
- fill-range "^7.0.1"
+ fill-range "^7.1.1"
browser-process-hrtime@^1.0.0:
version "1.0.0"
@@ -3395,7 +3402,7 @@ content-disposition@0.5.4:
dependencies:
safe-buffer "5.2.1"
-content-type@~1.0.4:
+content-type@~1.0.4, content-type@~1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
@@ -3410,10 +3417,10 @@ cookie-signature@1.0.6:
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
-cookie@0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
- integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
+cookie@0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
+ integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
copy-to-clipboard@^3.3.1:
version "3.3.3"
@@ -4467,16 +4474,16 @@ expect@^27.5.1:
jest-message-util "^27.5.1"
express@^4.17.3:
- version "4.18.2"
- resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
- integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
+ version "4.19.2"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465"
+ integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==
dependencies:
accepts "~1.3.8"
array-flatten "1.1.1"
- body-parser "1.20.1"
+ body-parser "1.20.2"
content-disposition "0.5.4"
content-type "~1.0.4"
- cookie "0.5.0"
+ cookie "0.6.0"
cookie-signature "1.0.6"
debug "2.6.9"
depd "2.0.0"
@@ -4530,9 +4537,9 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
fast-loops@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/fast-loops/-/fast-loops-1.1.3.tgz#ce96adb86d07e7bf9b4822ab9c6fac9964981f75"
- integrity sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g==
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/fast-loops/-/fast-loops-1.1.4.tgz#61bc77d518c0af5073a638c6d9d5c7683f069ce2"
+ integrity sha512-8dbd3XWoKCTms18ize6JmQF1SFnnfj5s0B7rRry22EofgMu7B6LKHVh+XfFqFGsqnbH54xgeO83PzpKI+ODhlg==
fast-shallow-equal@^1.0.0:
version "1.0.0"
@@ -4606,10 +4613,17 @@ filesize@^8.0.6:
resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8"
integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==
-fill-range@^7.0.1:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
- integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+fill-range@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
+ integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+fill-range@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
+ integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
dependencies:
to-regex-range "^5.0.1"
@@ -4677,9 +4691,9 @@ flatted@^3.1.0:
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
follow-redirects@^1.0.0:
- version "1.15.4"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.4.tgz#cdc7d308bf6493126b17ea2191ea0ccf3e535adf"
- integrity sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==
+ version "1.15.6"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
+ integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
for-each@^0.3.3:
version "0.3.3"
@@ -6476,11 +6490,11 @@ methods@~1.1.2:
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5:
- version "4.0.5"
- resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
- integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
+ integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
dependencies:
- braces "^3.0.2"
+ braces "^3.0.3"
picomatch "^2.3.1"
mime-db@1.52.0, "mime-db@>= 1.43.0 < 2":
@@ -7735,10 +7749,10 @@ range-parser@^1.2.1, range-parser@~1.2.1:
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
-raw-body@2.5.1:
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
- integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
+raw-body@2.5.2:
+ version "2.5.2"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a"
+ integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==
dependencies:
bytes "3.1.2"
http-errors "2.0.0"
@@ -9338,9 +9352,9 @@ webidl-conversions@^6.1.0:
integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
webpack-dev-middleware@^5.3.1:
- version "5.3.3"
- resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f"
- integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==
+ version "5.3.4"
+ resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz#eb7b39281cbce10e104eb2b8bf2b63fce49a3517"
+ integrity sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==
dependencies:
colorette "^2.0.10"
memfs "^3.4.3"
diff --git a/k8s-deploy/neodash/.helmignore b/k8s-deploy/neodash/.helmignore
new file mode 100644
index 000000000..0e8a0eb36
--- /dev/null
+++ b/k8s-deploy/neodash/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/k8s-deploy/neodash/Chart.yaml b/k8s-deploy/neodash/Chart.yaml
new file mode 100644
index 000000000..41e4e6c4e
--- /dev/null
+++ b/k8s-deploy/neodash/Chart.yaml
@@ -0,0 +1,24 @@
+apiVersion: v2
+name: neodash
+description: A NeoDash Helm chart for Kubernetes
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+type: application
+
+# This is the chart version. This version number should be incremented each time you make changes
+# to the chart and its templates, including the app version.
+# Versions are expected to follow Semantic Versioning (https://semver.org/)
+version: 1.0.0
+
+# This is the version number of the application being deployed. This version number should be
+# incremented each time you make changes to the application. Versions are not expected to
+# follow Semantic Versioning. They should reflect the version the application is using.
+# It is recommended to use it with quotes.
+appVersion: "2.4.9"
\ No newline at end of file
diff --git a/k8s-deploy/neodash/README.md b/k8s-deploy/neodash/README.md
new file mode 100644
index 000000000..0185710c9
--- /dev/null
+++ b/k8s-deploy/neodash/README.md
@@ -0,0 +1,78 @@
+# NeoDash
+
+![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.16.0](https://img.shields.io/badge/AppVersion-1.16.0-informational?style=flat-square)
+
+A NeoDash Helm chart for Kubernetes
+
+## Resources
+
+Following are the Kubernetes resources utilized for the NeoDash.
+
+- Deployment
+- Service
+- Ingress
+- Service Account
+- Horizontal Pod Autoscalar (HPA)
+
+## Values Configuration
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| autoscaling.enabled | bool | `false` | Enable/disable Autoscaling |
+| enable_reader_mode | bool | `true` | Enable/disable Reader mode |
+| envFromSecrets | list | `[]` | Environment variables from secrets |
+| fullnameOverride | string | `"neodash-test"` | Name override applies to all resources |
+| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
+| image.repository | string | `"neo4jlabs/neodash"` | Image repository and Image name |
+| image.tag | string | `"latest"` | Image version |
+| imagePullSecrets | list | `[]` | Image pull secrets if any |
+| podAnnotations | object | `{}` | Pod annotations |
+| podLabels | object | `{}` | Additional labels |
+| podSecurityContext | object | `{}` | Security Context if any |
+| ingress.annotations | object | `{}` | Ingress Annotations for load balancers |
+| ingress.className | string | `"alb"` | Ingress Class |
+| ingress.enabled | bool | `false` | Enable/disable Ingress |
+| ingress.hosts | list | `[]` | Host Details |
+| ingress.tls | list | `[]` | TLS details |
+| livenessProbe.httpGet.path | string | `"/*"` | LivenessProbe path |
+| livenessProbe.httpGet.port | int | `5005` | LivenessProbe port |
+| readinessProbe.httpGet.path | string | `"/*"` | Readiness path |
+| readinessProbe.httpGet.port | int | `5005` | Readiness port |
+| replicaCount | int | `1` | Replica count |
+| resources.limits.cpu | string | `"500m"` | CPU limit |
+| resources.limits.memory | string | `"128Mi"` | Memory limit |
+| resources.requests.cpu | string | `"250m"` | CPU request |
+| resources.requests.memory | string | `"64Mi"` | Memory request |
+| service.annotations | object | `{}` | Service annotations |
+| service.port | int | `5005` | Service port |
+| service.targetPort | int | `5005` | Service target port |
+| service.type | string | `"LoadBalancer"` | Type of service, other options are `ClusterIP` or `NodePort` |
+| serviceAccount.automount | bool | `true` | Enable/disable service account auto mount to pod |
+| serviceAccount.create | bool | `true` | Enable/disable service account |
+| volumeMounts | list | `[]` | Volume mounts on pod |
+| volumes | list | `[]` | Volumes for pod |
+| env | list |
- name: "ssoEnabled"
value: "false"
- name: "standalone"
value: "true"
- name: "standaloneProtocol"
value: "neo4j+s"
- name: "standaloneHost"
value: "localhost"
- name: "standalonePort"
value: "7687"
- name: "standaloneDatabase"
value: "neo4j"
- name: "standaloneDashboardName"
value: "test"
- name: "standaloneDashboardDatabase"
value: "neo4j"
- name: "standaloneAllowLoad"
value: "false"
- name: "standaloneLoadFromOtherDatabases"
value: "false"
- name: "standaloneMultiDatabase"
value: "false"
| Env variables for reader mode |
+
+## Usage
+
+- To install this helm chart run the following command,
+
+ ```bash
+ helm install