diff --git a/.eslintrc.json b/.eslintrc.json index c6d98d2c6..6f7a0eccf 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,8 +4,7 @@ "extends": ["eslint:recommended", "prettier", "plugin:@typescript-eslint/recommended"], // this is optional "env": { "browser": true, - "node": true, - "jest": true + "node": true }, "settings": { "react": { @@ -167,9 +166,5 @@ ], "symbol-description": "error", "yoda": "error" - }, - "globals": { - "cy": "readonly", - "Cypress": "readonly" } } diff --git a/.github/workflows/master-deployment.yml b/.github/workflows/master-deployment.yml index 820b12d8c..55cf525c4 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.9 + tags: ${{ secrets.DOCKER_HUB_LABS_USERNAME }}/neodash:latest,${{ secrets.DOCKER_HUB_LABS_USERNAME }}/neodash:2.4.8 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.9 + tags: ${{ secrets.DOCKER_HUB_USERNAME }}/neodash:latest,${{ secrets.DOCKER_HUB_USERNAME }}/neodash:2.4.8 deploy-gallery: runs-on: neodash-runners strategy: diff --git a/README.md b/README.md index 7ba0e71da..5c4db07c9 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,16 @@ -## NeoDash Labs - Neo4j Dashboard Builder +## 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. -![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. +![screenshot](public/screenshot.png) 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 Labs +## Try NeoDash You can run NeoDash in one of three ways: -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. +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. 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 @@ -87,4 +79,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 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 +> 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 diff --git a/changelog.md b/changelog.md index 9227e1fff..ae99c6f96 100644 --- a/changelog.md +++ b/changelog.md @@ -1,23 +1,3 @@ -## 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 93f8cffdf..73948909e 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -5,7 +5,6 @@ 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 deleted file mode 100644 index f90742a41..000000000 --- a/cypress/Page.js +++ /dev/null @@ -1,156 +0,0 @@ -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 new file mode 100644 index 000000000..3f9c20faa --- /dev/null +++ b/cypress/e2e/bar_chart.cy.js @@ -0,0 +1,316 @@ +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/charts/bar.cy.js b/cypress/e2e/charts/bar.cy.js deleted file mode 100644 index 80f13d640..000000000 --- a/cypress/e2e/charts/bar.cy.js +++ /dev/null @@ -1,211 +0,0 @@ -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/charts/array.cy.js b/cypress/e2e/render/array.cy.js similarity index 70% rename from cypress/e2e/charts/array.cy.js rename to cypress/e2e/render/array.cy.js index 1da231f01..108d4aceb 100644 --- a/cypress/e2e/charts/array.cy.js +++ b/cypress/e2e/render/array.cy.js @@ -1,9 +1,17 @@ import { stringArrayCypherQuery, intArrayCypherQuery, pathArrayCypherQuery } from '../../fixtures/cypher_queries'; -import { Page } from '../../Page'; +import { + enableReportActions, + createReportOfType, + closeSettings, + toggleTableTranspose, + openReportActionsMenu, + selectReportOfType, + openAdvancedSettings, + updateDropdownAdvancedSetting, +} from '../utils'; +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); @@ -12,34 +20,62 @@ Cypress.on('uncaught:exception', (err, runnable) => { describe('Testing array rendering', () => { beforeEach('open neodash', () => { - page.init().createNewDashboard().connectToNeo4j(); + 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(); cy.wait(100); }); it('creates a table that contains string arrays', () => { cy.checkInitialState(); - page.enableReportActions(); - page.createReportOfType('Table', stringArrayCypherQuery, true, true); + enableReportActions(); + 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 - page.updateDropdownAdvancedSetting('Transpose Rows & Columns', 'on'); - cy.get(`${CARD_SELECTOR} .MuiDataGrid-columnHeaderTitle:eq(1)`).should('have.text', 'initial,list'); + toggleTableTranspose(CARD_SELECTOR, true); + cy.get(`${CARD_SELECTOR} .MuiDataGrid-columnHeaderTitle:eq(1)`, { timeout: WAITING_TIME }).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 - page.updateDropdownAdvancedSetting('Transpose Rows & Columns', 'off'); - page.openReportActionsMenu(); + toggleTableTranspose(CARD_SELECTOR, false); + openReportActionsMenu(CARD_SELECTOR); 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(); - page.closeSettings(); + closeSettings(CARD_SELECTOR); cy.get(`${CARD_SELECTOR} .MuiDataGrid-cell:eq(0)`) .find('button') .should('be.visible') @@ -54,21 +90,24 @@ describe('Testing array rendering', () => { it('creates a table that contains int arrays', () => { cy.checkInitialState(); - page.createReportOfType('Table', intArrayCypherQuery, true, true); + 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 - page.updateDropdownAdvancedSetting('Transpose Rows & Columns', 'on'); - cy.get(`${CARD_SELECTOR} .MuiDataGrid-columnHeaderTitle:eq(1)`).should('have.text', '1,2'); + toggleTableTranspose(CARD_SELECTOR, true); + cy.get(`${CARD_SELECTOR} .MuiDataGrid-columnHeaderTitle:eq(1)`, { timeout: WAITING_TIME }).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(); - page.createReportOfType('Table', pathArrayCypherQuery, true, true); + 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'); @@ -81,13 +120,13 @@ describe('Testing array rendering', () => { it('creates a single value report which is an array', () => { cy.checkInitialState(); - page.createReportOfType('Single Value', stringArrayCypherQuery, true, true); + createReportOfType('Single Value', stringArrayCypherQuery, true, true); cy.get(CARD_SELECTOR).should('have.text', 'initial, list'); }); it('creates a multi parameter select', () => { cy.checkInitialState(); - page.selectReportOfType('Parameter Select'); + 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(); @@ -101,8 +140,8 @@ describe('Testing array rendering', () => { cy.wait(1000); cy.get('.MuiAutocomplete-popper').contains('title').click(); // Enable multiple selection - page.closeSettings(); - page.updateDropdownAdvancedSetting('Multiple Selection', 'on'); + closeSettings(CARD_SELECTOR); + updateDropdownAdvancedSetting(CARD_SELECTOR, '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/start_page.cy.js b/cypress/e2e/start_page.cy.js index 8038866b3..c6e9f7c4b 100644 --- a/cypress/e2e/start_page.cy.js +++ b/cypress/e2e/start_page.cy.js @@ -10,12 +10,9 @@ import { gaugeChartCypherQuery, formCypherQuery, } from '../fixtures/cypher_queries'; +import { createReportOfType, selectReportOfType, enableAdvancedVisualizations, enableFormsExtension } from './utils'; -import { Page } from '../Page'; - -const CARD_SELECTOR = 'main .react-grid-item:eq(2)'; -const page = new Page(CARD_SELECTOR); - +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); @@ -24,7 +21,40 @@ Cypress.on('uncaught:exception', (err, runnable) => { describe('NeoDash E2E Tests', () => { beforeEach(() => { - page.init().createNewDashboard().connectToNeo4j(); + 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(); cy.wait(100); }); @@ -55,7 +85,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') + cy.get('main .react-grid-item:eq(2) .MuiDataGrid-columnHeaders', { timeout: WAITING_TIME }) .should('contain', 'title') .and('contain', 'released') .and('not.contain', '__id'); @@ -68,25 +98,34 @@ describe('NeoDash E2E Tests', () => { it('creates a bar chart report', () => { cy.checkInitialState(); - page.createReportOfType('Bar Chart', barChartCypherQuery); - cy.get('main .react-grid-item:eq(2) #index input[name="Category"]').should('have.value', 'released'); + createReportOfType('Bar Chart', barChartCypherQuery); + cy.get('main .react-grid-item:eq(2) #index input[name="Category"]', { timeout: WAITING_TIME }).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(); - page.createReportOfType('Pie Chart', barChartCypherQuery); - cy.get('main .react-grid-item:eq(2) #index input[name="Category"]').should('have.value', 'released'); + createReportOfType('Pie Chart', barChartCypherQuery); + cy.get('main .react-grid-item:eq(2) #index input[name="Category"]', { timeout: WAITING_TIME }).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 > path').should('have.length', 5); + cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > g:nth-child(2) > path').should('have.length', 5); }); it('creates a line chart report', () => { cy.checkInitialState(); - page.createReportOfType('Line Chart', barChartCypherQuery); - cy.get('main .react-grid-item:eq(2) #x input[name="X-value"]').should('have.value', 'released'); + createReportOfType('Line Chart', barChartCypherQuery); + cy.get('main .react-grid-item:eq(2) #x input[name="X-value"]', { timeout: WAITING_TIME }).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( @@ -97,14 +136,19 @@ describe('NeoDash E2E Tests', () => { it('creates a map chart report', () => { cy.checkInitialState(); - page.createReportOfType('Map', mapChartCypherQuery, true); - cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > path').should('have.length', 5); + createReportOfType('Map', mapChartCypherQuery, true); + cy.get('main .react-grid-item:eq(2) .MuiCardContent-root svg > g > path', { timeout: WAITING_TIME }).should( + 'have.length', + 5 + ); }); it('creates a single value report', () => { cy.checkInitialState(); - page.createReportOfType('Single Value', barChartCypherQuery); - cy.get('main .react-grid-item:eq(2) .MuiCardContent-root > div > div:nth-child(2) > span') + createReportOfType('Single Value', barChartCypherQuery); + cy.get('main .react-grid-item:eq(2) .MuiCardContent-root > div > div:nth-child(2) > span', { + timeout: WAITING_TIME, + }) .invoke('text') .then((text) => { expect(text).to.be.oneOf(['1999', '1,999', '1 999']); @@ -112,49 +156,62 @@ describe('NeoDash E2E Tests', () => { }); it.skip('creates a gauge chart report', () => { - page.enableAdvancedVisualizations(); + enableAdvancedVisualizations(); cy.checkInitialState(); - page.createReportOfType('Gauge Chart', gaugeChartCypherQuery); - cy.get('.text-group > text').contains('69'); + createReportOfType('Gauge Chart', gaugeChartCypherQuery); + cy.get('.text-group > text', { timeout: WAITING_TIME }).contains('69'); }); it('creates a sunburst chart report', () => { - page.enableAdvancedVisualizations(); + enableAdvancedVisualizations(); cy.checkInitialState(); - page.createReportOfType('Sunburst Chart', sunburstChartCypherQuery); - cy.get('main .react-grid-item:eq(2) #index input[name="Path"]').should('have.value', 'x.path'); + createReportOfType('Sunburst Chart', sunburstChartCypherQuery); + cy.get('main .react-grid-item:eq(2) #index input[name="Path"]', { timeout: WAITING_TIME }).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', () => { - page.enableAdvancedVisualizations(); + enableAdvancedVisualizations(); cy.checkInitialState(); - page.createReportOfType('Circle Packing', sunburstChartCypherQuery); - cy.get('main .react-grid-item:eq(2) #index input[name="Path"]').should('have.value', 'x.path'); + createReportOfType('Circle Packing', sunburstChartCypherQuery); + cy.get('main .react-grid-item:eq(2) #index input[name="Path"]', { timeout: WAITING_TIME }).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', () => { - page.enableAdvancedVisualizations(); + enableAdvancedVisualizations(); cy.checkInitialState(); - page.createReportOfType('Treemap', sunburstChartCypherQuery); - cy.get('main .react-grid-item:eq(2) #index input[name="Path"]').should('have.value', 'x.path'); + createReportOfType('Treemap', sunburstChartCypherQuery); + cy.get('main .react-grid-item:eq(2) #index input[name="Path"]', { timeout: WAITING_TIME }).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', () => { - page.enableAdvancedVisualizations(); + enableAdvancedVisualizations(); cy.checkInitialState(); - 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); + 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 + ); }); it('creates a raw json report', () => { cy.checkInitialState(); - page.createReportOfType('Raw JSON', barChartCypherQuery); + 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(); @@ -165,7 +222,7 @@ describe('NeoDash E2E Tests', () => { it('creates a parameter select report', () => { cy.checkInitialState(); - page.selectReportOfType('Parameter Select'); + selectReportOfType('Parameter Select'); cy.wait(500); cy.get('#autocomplete-label-type').type('Movie'); cy.get('#autocomplete-label-type-option-0').click(); @@ -179,20 +236,20 @@ describe('NeoDash E2E Tests', () => { it('creates an iframe report', () => { cy.checkInitialState(); - page.createReportOfType('iFrame', iFrameText); + 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(); - page.createReportOfType('Markdown', markdownText); + 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', () => { - page.enableFormsExtension(); + enableFormsExtension(); cy.checkInitialState(); - page.createReportOfType('Form', formCypherQuery, true, false); + 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'); @@ -205,10 +262,8 @@ 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'); @@ -218,7 +273,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 { - const NUMBER_OF_PAGES_IN_STRESS_TEST_DASHBOARD = 5; + var 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/charts/table.cy.js b/cypress/e2e/table.cy.js similarity index 66% rename from cypress/e2e/charts/table.cy.js rename to cypress/e2e/table.cy.js index 5c086df1b..8ae2ac3c8 100644 --- a/cypress/e2e/charts/table.cy.js +++ b/cypress/e2e/table.cy.js @@ -1,7 +1,6 @@ -import { tableCypherQuery } from '../../fixtures/cypher_queries'; -import { Page } from '../../Page'; +import { tableCypherQuery } from '../fixtures/cypher_queries'; -const page = new Page(); +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); @@ -10,7 +9,30 @@ Cypress.on('uncaught:exception', (err, runnable) => { describe('Testing table', () => { beforeEach('open neodash', () => { - page.init().createNewDashboard().connectToNeo4j(); + 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); }); diff --git a/cypress/e2e/utils.js b/cypress/e2e/utils.js new file mode 100644 index 000000000..ae5639cf9 --- /dev/null +++ b/cypress/e2e/utils.js @@ -0,0 +1,84 @@ +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/commands.js b/cypress/support/commands.js index c7e9831e0..e486473bc 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -24,29 +24,61 @@ // -- 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 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.'); -}); + 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 diff --git a/cypress/index.js b/cypress/support/index.js similarity index 95% rename from cypress/index.js rename to cypress/support/index.js index cbfe0a766..37a498fb5 100644 --- a/cypress/index.js +++ b/cypress/support/index.js @@ -14,7 +14,7 @@ // *********************************************************** // Import commands.js using ES2015 syntax: -import './support/commands'; +import './commands'; // Alternatively you can use CommonJS syntax: // require('./commands') diff --git a/docs/modules/ROOT/pages/banner.adoc b/docs/modules/ROOT/pages/banner.adoc deleted file mode 100644 index fdb12c826..000000000 --- a/docs/modules/ROOT/pages/banner.adoc +++ /dev/null @@ -1,6 +0,0 @@ -[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 11ebdf886..dc47ee4ab 100644 --- a/docs/modules/ROOT/pages/developer-guide/adding-visualizations.adoc +++ b/docs/modules/ROOT/pages/developer-guide/adding-visualizations.adoc @@ -1,7 +1,5 @@ = Adding Visualizations -include::../banner.adoc[] - You can extend NeoDash with your own visualizations without diving deep into the core application. Likewise, adding a new customization to an existing report requires minimal changes. 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 df15e1c33..45cbc2641 100644 --- a/docs/modules/ROOT/pages/developer-guide/build-and-run.adoc +++ b/docs/modules/ROOT/pages/developer-guide/build-and-run.adoc @@ -1,7 +1,5 @@ = Build & Run -include::../banner.adoc[] - To start developing the application, you will need to set up the development environment. @@ -78,9 +76,7 @@ docker run -it –rm -p 5005:5005 neodash == Run on Kubernetes -=== 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: +An example of a pod definition YAML file to create a NeoDash pod in a cluster: .... apiVersion: v1 @@ -112,118 +108,3 @@ 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 da56627cb..e02da7989 100644 --- a/docs/modules/ROOT/pages/developer-guide/component-overview.adoc +++ b/docs/modules/ROOT/pages/developer-guide/component-overview.adoc @@ -1,6 +1,5 @@ = Component Overview -include::../banner.adoc[] The image below contains a high-level overview of the component hierarchy within the application. The following conceptual building diff --git a/docs/modules/ROOT/pages/developer-guide/configuration.adoc b/docs/modules/ROOT/pages/developer-guide/configuration.adoc index 03930186e..604ed1298 100644 --- a/docs/modules/ROOT/pages/developer-guide/configuration.adoc +++ b/docs/modules/ROOT/pages/developer-guide/configuration.adoc @@ -1,7 +1,5 @@ = Configuration -include::../banner.adoc[] - When using a custom NeoDash deployment, there are several settings that can be configured. These mostly relate to link:../standalone-mode[Standalone Mode] and SSO configurations. @@ -135,7 +133,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 |logs |When loggingMode is set to anything +|loggingDatabase |string |neo4j |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 40585f591..1cb695dde 100644 --- a/docs/modules/ROOT/pages/developer-guide/contributing.adoc +++ b/docs/modules/ROOT/pages/developer-guide/contributing.adoc @@ -1,7 +1,5 @@ = Contributing -include::../banner.adoc[] - Contributions to the project are highly welcomed. Please consider creating a https://github.com/neo4j-labs/neodash/pulls[Pull Request]. Ensure you start from the `develop` branch, and set the merge base to 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 0fce98736..a5f2fd529 100644 --- a/docs/modules/ROOT/pages/developer-guide/deploy-a-build.adoc +++ b/docs/modules/ROOT/pages/developer-guide/deploy-a-build.adoc @@ -1,7 +1,4 @@ = Deploy a Build - -include::../banner.adoc[] - 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. @@ -40,7 +37,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.9-labs username@host:/usr/share/nginx/html +scp neodash-2.4.8 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 ff32114c9..5f498bb2d 100644 --- a/docs/modules/ROOT/pages/developer-guide/design.adoc +++ b/docs/modules/ROOT/pages/developer-guide/design.adoc @@ -1,11 +1,5 @@ = Design -include::../banner.adoc[] - - -include::../banner.adoc[] - - This page contains some key guidelines for design of the application. This entails code architecture, as well as UX/UI design. diff --git a/docs/modules/ROOT/pages/developer-guide/index.adoc b/docs/modules/ROOT/pages/developer-guide/index.adoc index 63b9218fd..f4538d764 100644 --- a/docs/modules/ROOT/pages/developer-guide/index.adoc +++ b/docs/modules/ROOT/pages/developer-guide/index.adoc @@ -1,11 +1,5 @@ = Developer Guide -include::../banner.adoc[] - - -include::../banner.adoc[] - - This guide contains information for developers looking to deploy NeoDash, or extend it for their own needs. - link:build-and-run[Build & Run] diff --git a/docs/modules/ROOT/pages/developer-guide/session-storage.adoc b/docs/modules/ROOT/pages/developer-guide/session-storage.adoc index 17631fdb9..a4861a4cf 100644 --- a/docs/modules/ROOT/pages/developer-guide/session-storage.adoc +++ b/docs/modules/ROOT/pages/developer-guide/session-storage.adoc @@ -1,7 +1,5 @@ = Session Storage -include::../banner.adoc[] - This reducer serves only to store data that we want to reset at each new session. To connect to it, just define a key and use the predefined actions to set a new pair (key,value) inside of it. Inside the actions there is also an action to delete all the keys that match a precise prefix, it can be useful, for example, to wipe the sessionStorage state for a certain extension, if it stores the data inside the sessionStorage using a prefix (for example look at the query-translator extension at getSessionStorageHistoryKey). \ No newline at end of file diff --git a/docs/modules/ROOT/pages/developer-guide/standalone-mode.adoc b/docs/modules/ROOT/pages/developer-guide/standalone-mode.adoc index 63212dab1..f752cbad1 100644 --- a/docs/modules/ROOT/pages/developer-guide/standalone-mode.adoc +++ b/docs/modules/ROOT/pages/developer-guide/standalone-mode.adoc @@ -1,7 +1,5 @@ = Standalone Mode -include::../banner.adoc[] - Next to being a dashboard editor, NeoDash can be deployed in a `standalone mode' - allowing you set up a architecture to publish and read dashboards. diff --git a/docs/modules/ROOT/pages/developer-guide/state-management.adoc b/docs/modules/ROOT/pages/developer-guide/state-management.adoc index 72891086b..bdece9b9e 100644 --- a/docs/modules/ROOT/pages/developer-guide/state-management.adoc +++ b/docs/modules/ROOT/pages/developer-guide/state-management.adoc @@ -1,7 +1,5 @@ = State Management -include::../banner.adoc[] - NeoDash is an application with a complex internal state. If you are planning to extend the application state in some way, make sure you are familiar with https://redux.js.org/[Redux] design patterns. diff --git a/docs/modules/ROOT/pages/developer-guide/style-configuration.adoc b/docs/modules/ROOT/pages/developer-guide/style-configuration.adoc index f86a73b57..b82124d2f 100644 --- a/docs/modules/ROOT/pages/developer-guide/style-configuration.adoc +++ b/docs/modules/ROOT/pages/developer-guide/style-configuration.adoc @@ -1,7 +1,5 @@ = Style Configuration -include::../banner.adoc[] - When using a custom NeoDash deployment, there are several theme variables that can be configured. These mostly relate to css tokens for link:https://cdn.jsdelivr.net/npm/@neo4j-ndl/base@1.4.0/lib/tokens/css/tokens.css[Needle] and some other brand specific options. @@ -16,7 +14,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 9bdd93b06..402ed1bca 100644 --- a/docs/modules/ROOT/pages/developer-guide/testing.adoc +++ b/docs/modules/ROOT/pages/developer-guide/testing.adoc @@ -1,7 +1,5 @@ = Testing -include::../banner.adoc[] - NeoDash uses *Cypress* for automated testing. To install Cypress, check out the official https://docs.cypress.io/guides/getting-started/installing-cypress#What-you-ll-learn[installation diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 7223154d9..6c7816dce 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -1,7 +1,4 @@ = Introduction - -include::/banner.adoc[] - This portal contains information on getting started with NeoDash - A Low-Code Dashboard Builder for Neo4j. 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. diff --git a/docs/modules/ROOT/pages/quickstart.adoc b/docs/modules/ROOT/pages/quickstart.adoc index 56a341a5d..b128dac71 100644 --- a/docs/modules/ROOT/pages/quickstart.adoc +++ b/docs/modules/ROOT/pages/quickstart.adoc @@ -1,7 +1,5 @@ = Quickstart -include::/banner.adoc[] - There are three easy ways to run NeoDash and start dashboarding your Neo4j data: . The latest version is always available online: diff --git a/docs/modules/ROOT/pages/user-guide/access-control.adoc b/docs/modules/ROOT/pages/user-guide/access-control.adoc index 7f3f54e35..03c62dfd1 100644 --- a/docs/modules/ROOT/pages/user-guide/access-control.adoc +++ b/docs/modules/ROOT/pages/user-guide/access-control.adoc @@ -1,7 +1,5 @@ = Access Control -include::../banner.adoc[] - 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 4618f2f2c..8acdc4e92 100644 --- a/docs/modules/ROOT/pages/user-guide/bloom-integration.adoc +++ b/docs/modules/ROOT/pages/user-guide/bloom-integration.adoc @@ -1,7 +1,5 @@ = Bloom Integration -include::../banner.adoc[] - NeoDash can be linked to Neo4j Bloom perspectives by using https://neo4j.com/docs/bloom-user-guide/current/bloom-tutorial/deep-links/[Bloom Deep Links]. This functionality allows you to combine the power of graph diff --git a/docs/modules/ROOT/pages/user-guide/dashboards.adoc b/docs/modules/ROOT/pages/user-guide/dashboards.adoc index 87e3f291c..dc6b70571 100644 --- a/docs/modules/ROOT/pages/user-guide/dashboards.adoc +++ b/docs/modules/ROOT/pages/user-guide/dashboards.adoc @@ -1,7 +1,5 @@ = Dashboards -include::../banner.adoc[] - In NeoDash, a dashboard consists of several pages, each of which can consist of multiple reports. 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 d96aa78be..941b4dbda 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,7 +1,5 @@ = Access Control Management -include::../../banner.adoc[] - 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. This extension is only visible to users with the role of "Administrator" or "Super User". Enabling this extension will allow the admin user to manage the labels of the roles in the database and then attach them to the users. 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 3107de146..fb02c5a94 100644 --- a/docs/modules/ROOT/pages/user-guide/extensions/advanced-visualizations.adoc +++ b/docs/modules/ROOT/pages/user-guide/extensions/advanced-visualizations.adoc @@ -1,7 +1,5 @@ = Advanced Visualizations -include::../../banner.adoc[] - Advanced visualizations let you extend your dashboard with complex, powerful visualizations beyond the standard visualizations. For specific use-cases, these visualizations may convey information that a simple visualization cannot. To use advanced visualizations, enable them in the **Extensions Window**. This makes them selectable inside reports, as well as add examples to the Example window. diff --git a/docs/modules/ROOT/pages/user-guide/extensions/forms.adoc b/docs/modules/ROOT/pages/user-guide/extensions/forms.adoc index a11fa9eda..4bce11d4d 100644 --- a/docs/modules/ROOT/pages/user-guide/extensions/forms.adoc +++ b/docs/modules/ROOT/pages/user-guide/extensions/forms.adoc @@ -1,7 +1,5 @@ = Forms -include::../../banner.adoc[] - The 'forms' extension lets you combine different parameter selectors to update / modify your graph data. Update queries are predefined by the dashboard builder, and the user is limited to specifying the parameters for the query only. diff --git a/docs/modules/ROOT/pages/user-guide/extensions/index.adoc b/docs/modules/ROOT/pages/user-guide/extensions/index.adoc index e4f589499..f267315ff 100644 --- a/docs/modules/ROOT/pages/user-guide/extensions/index.adoc +++ b/docs/modules/ROOT/pages/user-guide/extensions/index.adoc @@ -1,7 +1,5 @@ = Extensions -include::../../banner.adoc[] - Extensions provide a way to expand the basic functionality of NeoDash with extra features. To enable an extension, open up the extensions window by clicking the puzzle piece icon in the left-sidebar of the screen. This will open up the **Extensions Window**, which lets you toggle active extensions for the current dashboard. 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 4ea475ca8..e7f9ea059 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,7 +1,4 @@ = Text2Cypher - Natural Language Queries - -include::../../banner.adoc[] - 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. == How it works 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 a2192a5fa..8b50f1651 100644 --- a/docs/modules/ROOT/pages/user-guide/extensions/report-actions.adoc +++ b/docs/modules/ROOT/pages/user-guide/extensions/report-actions.adoc @@ -1,7 +1,5 @@ = Report Actions -include::../../banner.adoc[] - link:../#_2_pro_extensions[label:Pro Extension[]] Report actions let dashboard builders add interactivity into dashboards. Actions can be used to achieve: 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 a68a8525a..ee6adc4ca 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,6 +1,5 @@ = Rule-Based Styling -include::../../banner.adoc[] The rule-based styling extension allows users to dynamically color elements in a visualization based on output values. This can be applied to tables, graphs, bar charts, line charts, and more. To use the extension, click on the 'rule-based styling' icon inside the settings of a report. diff --git a/docs/modules/ROOT/pages/user-guide/extensions/workflows.adoc b/docs/modules/ROOT/pages/user-guide/extensions/workflows.adoc index f94f8f52e..2b95b06d5 100644 --- a/docs/modules/ROOT/pages/user-guide/extensions/workflows.adoc +++ b/docs/modules/ROOT/pages/user-guide/extensions/workflows.adoc @@ -1,7 +1,5 @@ = Workflows -include::../../banner.adoc[] - 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. == Enable the extension diff --git a/docs/modules/ROOT/pages/user-guide/faq.adoc b/docs/modules/ROOT/pages/user-guide/faq.adoc index 4dfe5b7ce..cdd5efaad 100644 --- a/docs/modules/ROOT/pages/user-guide/faq.adoc +++ b/docs/modules/ROOT/pages/user-guide/faq.adoc @@ -1,7 +1,5 @@ = FAQ -include::../banner.adoc[] - == 1. How can I learn more about NeoDash? To learn more, check out the following list of resources (blogs, videos diff --git a/docs/modules/ROOT/pages/user-guide/index.adoc b/docs/modules/ROOT/pages/user-guide/index.adoc index 87cf337e9..dde9d9e05 100644 --- a/docs/modules/ROOT/pages/user-guide/index.adoc +++ b/docs/modules/ROOT/pages/user-guide/index.adoc @@ -1,7 +1,5 @@ = User Guide -include::../banner.adoc[] - 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 d49807656..b332e4ae7 100644 --- a/docs/modules/ROOT/pages/user-guide/pages.adoc +++ b/docs/modules/ROOT/pages/user-guide/pages.adoc @@ -1,7 +1,5 @@ = Pages -include::../banner.adoc[] - A page is a collection of link:../reports[reports] that can be viewed at the same time. Each page can have an unlimited number of reports in it, and will switch to a scrollable view when the number of reports do not diff --git a/docs/modules/ROOT/pages/user-guide/publishing.adoc b/docs/modules/ROOT/pages/user-guide/publishing.adoc index 40dab6fc0..2b1015a03 100644 --- a/docs/modules/ROOT/pages/user-guide/publishing.adoc +++ b/docs/modules/ROOT/pages/user-guide/publishing.adoc @@ -1,7 +1,5 @@ = Publishing -include::/banner.adoc[] - When you are done building a dashboard, you may want to *publish* that dashboard for others to view. The workflow for a continuous dashboarding cycle may look something like this: diff --git a/docs/modules/ROOT/pages/user-guide/reports/areamap.adoc b/docs/modules/ROOT/pages/user-guide/reports/areamap.adoc index 65e1f5e83..d28f4c6bc 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/areamap.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/areamap.adoc @@ -1,7 +1,5 @@ = Area Map -include::../../banner.adoc[] - link:../../extensions/advanced-visualizations[label:Advanced Visualization[]] The Area Map charts can be used to render geographical based information on geoJson polygons. It's possible to click a polygon to visualize its regions and their related data. 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 58cbd1763..56a8773c1 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/bar-chart.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/bar-chart.adoc @@ -1,7 +1,5 @@ = Bar Chart -include::../../banner.adoc[] - A bar chart will draw categories and values in a familiar bar-layout. The bar chart will require you to choose the following selections: diff --git a/docs/modules/ROOT/pages/user-guide/reports/choropleth.adoc b/docs/modules/ROOT/pages/user-guide/reports/choropleth.adoc index 9d8ac8ca1..35fdbdd19 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/choropleth.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/choropleth.adoc @@ -1,7 +1,5 @@ = Choropleth -include::../../banner.adoc[] - link:../../extensions/advanced-visualizations[label:Advanced Visualization[]] A Choropleth chart will render geographical data in geoJson polygons 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 9b19d26a5..61146b24d 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/circle-packing.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/circle-packing.adoc @@ -1,7 +1,5 @@ = Circle Packing -include::../../banner.adoc[] - link:../../extensions/advanced-visualizations[label:Advanced Visualization[]] A circle packing chart will render hierarchical data in a group of diff --git a/docs/modules/ROOT/pages/user-guide/reports/form.adoc b/docs/modules/ROOT/pages/user-guide/reports/form.adoc index 3ca3823b3..d7817f171 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/form.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/form.adoc @@ -1,7 +1,5 @@ = Form -include::../../banner.adoc[] - A form is a special type of report that lets users run predefined, parameterized queries. A single form can consist of: diff --git a/docs/modules/ROOT/pages/user-guide/reports/gantt.adoc b/docs/modules/ROOT/pages/user-guide/reports/gantt.adoc index ca141db70..c54567aa5 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/gantt.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/gantt.adoc @@ -1,7 +1,5 @@ = Gantt Chart -include::../../banner.adoc[] - link:../../extensions/advanced-visualizations[label:Advanced Visualization[]] A Gantt chart can be used to visualize tasks on a timeline, as well as their dependencies. 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 2db58ac39..067acd6aa 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/gauge-chart.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/gauge-chart.adoc @@ -1,7 +1,5 @@ = Gauge Chart -include::../../banner.adoc[] - link:../../extensions/advanced-visualizations[label:Advanced Visualization[]] A gauge chart takes a single numeric value, and plots it on an animated gauge: diff --git a/docs/modules/ROOT/pages/user-guide/reports/graph.adoc b/docs/modules/ROOT/pages/user-guide/reports/graph.adoc index 0d3dd7ff0..4d18523dd 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/graph.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/graph.adoc @@ -1,7 +1,5 @@ = Graph -include::../../banner.adoc[] - The graph report will render all returned nodes, relationships and paths in a force-directed graph layout. This includes collections (lists) of these objects. diff --git a/docs/modules/ROOT/pages/user-guide/reports/graph3d.adoc b/docs/modules/ROOT/pages/user-guide/reports/graph3d.adoc index f890c8032..31d2ef6a2 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/graph3d.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/graph3d.adoc @@ -1,7 +1,5 @@ = 3D Graph -include::../../banner.adoc[] - link:../../extensions/advanced-visualizations[label:Advanced Visualization[]] The 3D graph report extends the default graph visualization with another dimension. diff --git a/docs/modules/ROOT/pages/user-guide/reports/iframe.adoc b/docs/modules/ROOT/pages/user-guide/reports/iframe.adoc index 86aed6cd0..44e822e08 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/iframe.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/iframe.adoc @@ -1,7 +1,5 @@ = iFrame -include::../../banner.adoc[] - An iFrame report lets you embed a webpage inside your NeoDash dashboard. The page can be loaded from any web address starting with `http://` or `https://`, with some exceptions*. diff --git a/docs/modules/ROOT/pages/user-guide/reports/index.adoc b/docs/modules/ROOT/pages/user-guide/reports/index.adoc index e1d0dc083..da44ed606 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/index.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/index.adoc @@ -1,7 +1,5 @@ = Reports -include::../../banner.adoc[] - A report is the smallest building build of your dashboard. Each report will have a single Cypher query behind it that is used to populate the report. Reports can be of several types (graph, table, bar chart, etc.), 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 0bf0fd5e1..ec0c21d52 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/line-chart.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/line-chart.adoc @@ -1,7 +1,5 @@ = Line Chart -include::../../banner.adoc[] - A line chart can be used to draw one or more lines in a two-dimensional plane. It requires two numeric fields: diff --git a/docs/modules/ROOT/pages/user-guide/reports/map.adoc b/docs/modules/ROOT/pages/user-guide/reports/map.adoc index 3d22d132d..081b917f2 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/map.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/map.adoc @@ -1,7 +1,5 @@ = Map -include::../../banner.adoc[] - The map report will render all returned nodes, relationships and paths on a geomap. https://www.openstreetmap.org[Open Street Map] is used to visualize the data on the map. diff --git a/docs/modules/ROOT/pages/user-guide/reports/markdown.adoc b/docs/modules/ROOT/pages/user-guide/reports/markdown.adoc index dc7bd0260..fc09c3726 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/markdown.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/markdown.adoc @@ -1,7 +1,5 @@ = Markdown -include::../../banner.adoc[] - Markdown reports let you specify https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#styling-text[Markdown] text, to be renderer as rich HTML. This lets you turn your dashboards 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 872ef4bc0..2951b7133 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/parameter-select.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/parameter-select.adoc @@ -1,7 +1,4 @@ = Parameter Select - -include::../../banner.adoc[] - 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 79f56848c..9300388a7 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/pie-chart.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/pie-chart.adoc @@ -1,7 +1,5 @@ = Pie Chart -include::../../banner.adoc[] - A pie chart will draw categories and values in a circular disc layout. The pie chart will require you to choose the following selections: diff --git a/docs/modules/ROOT/pages/user-guide/reports/radar.adoc b/docs/modules/ROOT/pages/user-guide/reports/radar.adoc index ab2200fe8..4cd805e22 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/radar.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/radar.adoc @@ -1,7 +1,5 @@ = Radar Chart -include::../../banner.adoc[] - link:../../extensions/advanced-visualizations[label:Advanced Visualization[]] A Radar chart can be used to render multivariate data from an array of nodes 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 f97c1783b..cf523529e 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/raw-json.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/raw-json.adoc @@ -1,7 +1,5 @@ = Raw JSON -include::../../banner.adoc[] - The Raw JSON report renders the JSON response received from Neo4j directly. This is typically used for debugging queries, or, understanding the exact data types being returned 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 2b6374672..f725d2d3e 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/sankey.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/sankey.adoc @@ -1,7 +1,5 @@ = Sankey Chart -include::../../banner.adoc[] - link:../../extensions/advanced-visualizations[label:Advanced Visualization[]] A Sankey visualization will generate a flow diagram from nodes and links. 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 e855df92f..593f92a11 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/single-value.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/single-value.adoc @@ -1,7 +1,5 @@ = Single Value -include::../../banner.adoc[] - A single value report will render the first column of the first row returned by the Cypher query. Single value reports are typically used for key metrics: diff --git a/docs/modules/ROOT/pages/user-guide/reports/sunburst.adoc b/docs/modules/ROOT/pages/user-guide/reports/sunburst.adoc index 30a73fe61..c3385bcdc 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/sunburst.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/sunburst.adoc @@ -1,7 +1,5 @@ = Sunburst -include::../../banner.adoc[] - link:../../extensions/advanced-visualizations[label:Advanced Visualization[]] A sunburst chart will render hierarchical data in a multi-level pie diff --git a/docs/modules/ROOT/pages/user-guide/reports/table.adoc b/docs/modules/ROOT/pages/user-guide/reports/table.adoc index 675daa003..8bb11cb14 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/table.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/table.adoc @@ -1,7 +1,5 @@ = Table -include::../../banner.adoc[] - The most common report in a dashboard is often a simple table view. NeoDash contains a powerful table component that can render all the data returned by a Cypher query. This includes simple data like numbers or diff --git a/docs/modules/ROOT/pages/user-guide/reports/treemap.adoc b/docs/modules/ROOT/pages/user-guide/reports/treemap.adoc index 23c96a69e..9a07ec12a 100644 --- a/docs/modules/ROOT/pages/user-guide/reports/treemap.adoc +++ b/docs/modules/ROOT/pages/user-guide/reports/treemap.adoc @@ -1,7 +1,5 @@ = Treemap -include::../../banner.adoc[] - link:../../extensions/advanced-visualizations[label:Advanced Visualization[]] A treemap chart will render hierarchical data in a nested rectangle diff --git a/evolving.png b/evolving.png deleted file mode 100644 index ebc85364b..000000000 Binary files a/evolving.png and /dev/null differ diff --git a/gallery/yarn.lock b/gallery/yarn.lock index aa9a0cde5..75b7590fc 100644 --- a/gallery/yarn.lock +++ b/gallery/yarn.lock @@ -3042,19 +3042,12 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -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: +braces@^3.0.2, 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.1.1" + fill-range "^7.0.1" browser-process-hrtime@^1.0.0: version "1.0.0" @@ -4537,9 +4530,9 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fast-loops@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/fast-loops/-/fast-loops-1.1.4.tgz#61bc77d518c0af5073a638c6d9d5c7683f069ce2" - integrity sha512-8dbd3XWoKCTms18ize6JmQF1SFnnfj5s0B7rRry22EofgMu7B6LKHVh+XfFqFGsqnbH54xgeO83PzpKI+ODhlg== + 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== fast-shallow-equal@^1.0.0: version "1.0.0" @@ -4613,17 +4606,10 @@ filesize@^8.0.6: resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8" integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ== -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== +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== dependencies: to-regex-range "^5.0.1" @@ -4691,9 +4677,9 @@ flatted@^3.1.0: integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== follow-redirects@^1.0.0: - version "1.15.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" - integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + version "1.15.4" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.4.tgz#cdc7d308bf6493126b17ea2191ea0ccf3e535adf" + integrity sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw== for-each@^0.3.3: version "0.3.3" @@ -6490,11 +6476,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.8" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" - integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: - braces "^3.0.3" + braces "^3.0.2" picomatch "^2.3.1" mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": diff --git a/k8s-deploy/neodash/.helmignore b/k8s-deploy/neodash/.helmignore deleted file mode 100644 index 0e8a0eb36..000000000 --- a/k8s-deploy/neodash/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# 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 deleted file mode 100644 index 41e4e6c4e..000000000 --- a/k8s-deploy/neodash/Chart.yaml +++ /dev/null @@ -1,24 +0,0 @@ -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 deleted file mode 100644 index 0185710c9..000000000 --- a/k8s-deploy/neodash/README.md +++ /dev/null @@ -1,78 +0,0 @@ -# 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 ./neodash -n - ``` - -- To upgrade the release run the following command, - - ```bash - helm upgrade ./neodash -n - ``` - -- To uninstall the release run the following command, - - ```bash - helm uninstall -n - ``` - -> **Note:** To use custom values files, pass `-f .yaml` for the above command. -> **Note:** To use custom values, pass `--set param=value` for the above command. -For example, to install neodash and set the service type to NodePort, run: `helm install ./neodash -n --set service.type=NodePort` diff --git a/k8s-deploy/neodash/templates/NOTES.txt b/k8s-deploy/neodash/templates/NOTES.txt deleted file mode 100644 index 099242813..000000000 --- a/k8s-deploy/neodash/templates/NOTES.txt +++ /dev/null @@ -1,26 +0,0 @@ -The NeoDash application has been successfully deployed, here is the application URL: -{{- if .Values.ingress.enabled }} -{{- range $host := .Values.ingress.hosts }} - {{- range .paths }} - http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} - {{- end }} -{{- end }} -{{- else if contains "NodePort" .Values.service.type }} - Run the following command to retrieve the IP address: - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "neodash.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT -{{- else if contains "LoadBalancer" .Values.service.type }} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of the LoadBalancer by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "neodash.fullname" . }}' - - Once available, run the following command to retrieve the IP address: - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "neodash.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - echo http://$SERVICE_IP:{{ .Values.service.port }} -{{- else if contains "ClusterIP" .Values.service.type }} - Run the following command to retrieve the IP address: - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "neodash.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") - export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") - echo "Visit http://127.0.0.1:8080 to use your application" - kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT -{{- end }} \ No newline at end of file diff --git a/k8s-deploy/neodash/templates/_helpers.tpl b/k8s-deploy/neodash/templates/_helpers.tpl deleted file mode 100644 index 9bb54f5c5..000000000 --- a/k8s-deploy/neodash/templates/_helpers.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "neodash.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "neodash.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "neodash.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "neodash.labels" -}} -helm.sh/chart: {{ include "neodash.chart" . }} -{{ include "neodash.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "neodash.selectorLabels" -}} -app.kubernetes.io/name: {{ include "neodash.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "neodash.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "neodash.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/k8s-deploy/neodash/templates/deployment.yaml b/k8s-deploy/neodash/templates/deployment.yaml deleted file mode 100644 index 63778a9c1..000000000 --- a/k8s-deploy/neodash/templates/deployment.yaml +++ /dev/null @@ -1,76 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "neodash.fullname" . }} - labels: - {{- include "neodash.labels" . | nindent 4 }} -spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "neodash.selectorLabels" . | nindent 6 }} - template: - metadata: - {{- with .Values.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "neodash.labels" . | nindent 8 }} - {{- with .Values.podLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "neodash.serviceAccountName" . }} - automountServiceAccountToken: false - containers: - - name: {{ .Chart.Name }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - {{- with .Values.podSecurityContext }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 12 }} - {{- end }} - ports: - - name: http - containerPort: {{ .Values.service.targetPort }} - protocol: TCP - env: - {{- if ne 5005 (int .Values.service.targetPort) }} - - name: NGINX_PORT - value: {{ .Values.service.port | quote }} - {{- end }} - {{- if .Values.enable_reader_mode}} - {{- with .Values.env }} - {{- toYaml . | nindent 12 }} - {{- end }} - {{- if .Values.envFromSecrets }} - {{- range $key, $value := .Values.envFromSecrets }} - - name: {{ $key }} - valueFrom: - secretKeyRef: - name: {{ $value.secretName }} - key: {{ $value.key }} - {{- end }} - {{- end }} - {{- end }} - livenessProbe: - {{- toYaml .Values.livenessProbe | nindent 12 }} - readinessProbe: - {{- toYaml .Values.readinessProbe | nindent 12 }} - resources: - {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.volumeMounts }} - volumeMounts: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.volumes }} - volumes: - {{- toYaml . | nindent 8 }} - {{- end }} \ No newline at end of file diff --git a/k8s-deploy/neodash/templates/hpa.yaml b/k8s-deploy/neodash/templates/hpa.yaml deleted file mode 100644 index ce2bae2db..000000000 --- a/k8s-deploy/neodash/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "neodash.fullname" . }} - labels: - {{- include "neodash.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "neodash.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/k8s-deploy/neodash/templates/ingress.yaml b/k8s-deploy/neodash/templates/ingress.yaml deleted file mode 100644 index 8dccdc279..000000000 --- a/k8s-deploy/neodash/templates/ingress.yaml +++ /dev/null @@ -1,61 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $fullName := include "neodash.fullname" . -}} -{{- $svcPort := .Values.service.port -}} -{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }} - labels: - {{- include "neodash.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.ingress.className }} - {{- end }} - {{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} - pathType: {{ .pathType }} - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ $fullName }} - port: - number: {{ $svcPort }} - {{- else }} - serviceName: {{ $fullName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} diff --git a/k8s-deploy/neodash/templates/service.yaml b/k8s-deploy/neodash/templates/service.yaml deleted file mode 100644 index b1080ab59..000000000 --- a/k8s-deploy/neodash/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "neodash.fullname" . }} - labels: - {{- include "neodash.labels" . | nindent 4 }} - {{- with .Values.service.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: {{ .Values.service.targetPort }} - protocol: TCP - name: http - selector: - {{- include "neodash.selectorLabels" . | nindent 4 }} \ No newline at end of file diff --git a/k8s-deploy/neodash/templates/serviceaccount.yaml b/k8s-deploy/neodash/templates/serviceaccount.yaml deleted file mode 100644 index a7dd2c3ac..000000000 --- a/k8s-deploy/neodash/templates/serviceaccount.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "neodash.serviceAccountName" . }} - labels: - {{- include "neodash.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -automountServiceAccountToken: {{ .Values.serviceAccount.automount }} -{{- end }} diff --git a/k8s-deploy/neodash/templates/tests/test-connection.yaml b/k8s-deploy/neodash/templates/tests/test-connection.yaml deleted file mode 100644 index b7def4d87..000000000 --- a/k8s-deploy/neodash/templates/tests/test-connection.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: "{{ include "neodash.fullname" . }}-test-connection" - labels: - {{- include "neodash.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": test -spec: - automountServiceAccountToken: false - containers: - - name: wget - image: busybox - command: ['wget'] - args: ['{{ include "neodash.fullname" . }}:{{ .Values.service.port }}'] - resources: - {{- toYaml .Values.resources | nindent 8 }} - restartPolicy: Never diff --git a/k8s-deploy/neodash/values.yaml b/k8s-deploy/neodash/values.yaml deleted file mode 100644 index 56b781213..000000000 --- a/k8s-deploy/neodash/values.yaml +++ /dev/null @@ -1,108 +0,0 @@ -# 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/k8s-deploy/sample-k8s-yamls/deployment.yaml b/k8s-deploy/sample-k8s-yamls/deployment.yaml deleted file mode 100644 index e9e490a27..000000000 --- a/k8s-deploy/sample-k8s-yamls/deployment.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -# Source: neodash/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: neodash - labels: - application: neodash-deploy -spec: - replicas: 1 - selector: - matchLabels: - application: neodash-deploy - template: - metadata: - labels: - application: neodash-deploy - spec: - serviceAccountName: neodash-test - automountServiceAccountToken: false - containers: - - name: neodash - image: "neo4jlabs/neodash:latest" - imagePullPolicy: IfNotPresent - ports: - - name: http - containerPort: 5005 - protocol: TCP - 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" - livenessProbe: - httpGet: - path: /* - port: 5005 - readinessProbe: - httpGet: - path: /* - port: 5005 - resources: - limits: - cpu: 500m - memory: 128Mi - requests: - cpu: 250m - memory: 64Mi \ No newline at end of file diff --git a/k8s-deploy/sample-k8s-yamls/service.yaml b/k8s-deploy/sample-k8s-yamls/service.yaml deleted file mode 100644 index 28633b71c..000000000 --- a/k8s-deploy/sample-k8s-yamls/service.yaml +++ /dev/null @@ -1,17 +0,0 @@ ---- -# Source: neodash/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: neodash - labels: - application: neodash-deploy -spec: - type: LoadBalancer - ports: - - port: 5005 - targetPort: 5005 - protocol: TCP - name: http - selector: - application: neodash-deploy \ No newline at end of file diff --git a/package.json b/package.json index 1ed5096e2..6200bb3a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "neodash", - "version": "2.4.9", + "version": "2.4.8", "description": "NeoDash - Neo4j Dashboard Builder", "neo4jDesktop": { "apiVersion": "^1.2.0" @@ -30,8 +30,7 @@ "lint": "eslint --ext .ts --ext .tsx .", "lint-staged": "lint-staged --config .lintstagedrc.json", "test": "yarn cypress open", - "test-headless": "yarn cypress run", - "prepare": "husky install" + "test-headless": "yarn cypress run" }, "keywords": [], "author": "Neo4j Labs", @@ -43,7 +42,7 @@ "@mui/icons-material": "^5.14.3", "@mui/material": "^5.12.3", "@mui/styles": "^5.12.3", - "@mui/x-data-grid": "7.4.0", + "@mui/x-data-grid": "5.17.26", "@mui/x-date-pickers": "^5.0.17", "@neo4j-cypher/react-codemirror": "^1.0.3", "@neo4j-ndl/base": "1.10.3", @@ -104,7 +103,6 @@ "tailwindcss": "^3.3.2", "three": "^0.159.0", "three-spritetext": "^1.8.1", - "urijs": "^1.19.11", "use-neo4j": "^0.3.13", "yaml": "^2.2.1" }, diff --git a/release-notes.md b/release-notes.md index 68200808b..ea7c80484 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,19 +1,9 @@ -## 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) \ No newline at end of file +## NeoDash 2.4.8 +This is a minor release containing an important fix and other minor fixes: + +- Fixed a bug where loading a dashboard would reset parameters to null ([887](https://github.com/neo4j-labs/neodash/pull/887)). +- Fix relationship width parameter for Graph report ([889](https://github.com/neo4j-labs/neodash/pull/889)). + +Thanks to all the contributors for this release: +- [alfredorubin96](https://github.com/alfredorubin96), +- [nielsdejong](https://github.com/nielsdejong). \ No newline at end of file diff --git a/src/application/ApplicationThunks.ts b/src/application/ApplicationThunks.ts index ac1d87222..46d2cd54e 100644 --- a/src/application/ApplicationThunks.ts +++ b/src/application/ApplicationThunks.ts @@ -261,6 +261,7 @@ export const handleSharedDashboardsThunk = () => (dispatch: any) => { if (dashboardDatabase) { dispatch(setStandaloneDashboardDatabase(dashboardDatabase)); } + if (urlParams.get('credentials')) { setWelcomeScreenOpen(false); const connection = decodeURIComponent(urlParams.get('credentials')); @@ -270,6 +271,32 @@ export const handleSharedDashboardsThunk = () => (dispatch: any) => { const database = connection.split('@')[1].split(':')[0]; const url = connection.split('@')[1].split(':')[1]; const port = connection.split('@')[1].split(':')[2]; + // if (url == password) { + // // Special case where a connect link is generated without a password. + // // Here, the format is parsed incorrectly and we open the connection window instead. + // dispatch(setConnectionProperties(protocol, url, port, database, username.split('@')[0], '')); + // dispatch( + // setShareDetailsFromUrl( + // type, + // id, + // standalone, + // protocol, + // url, + // port, + // database, + // username.split('@')[0], + // '', + // dashboardDatabase, + // true + // ) + // ); + // setDashboardToLoadAfterConnecting(id); + // window.history.pushState({}, document.title, window.location.pathname); + // dispatch(setConnectionModalOpen(true)); + // dispatch(setWelcomeScreenOpen(false)); + // // window.history.pushState({}, document.title, "/"); + // return; + // } dispatch(setConnectionModalOpen(false)); dispatch( @@ -300,7 +327,7 @@ export const handleSharedDashboardsThunk = () => (dispatch: any) => { setShareDetailsFromUrl( type, id, - standalone, + undefined, undefined, undefined, undefined, @@ -358,7 +385,6 @@ export const onConfirmLoadSharedDashboardThunk = () => (dispatch: any, getState: } if (shareDetails.standalone == true) { dispatch(setStandaloneMode(true)); - localStorage.setItem('standaloneShared', 'true'); // EDGE CASE: redirect SSO removes the shareDetails when redirecting } dispatch(resetShareDetails()); } catch (e) { @@ -425,13 +451,10 @@ export const loadApplicationConfigThunk = () => async (dispatch: any, getState: dispatch(setSSOEnabled(config.ssoEnabled, state.application.cachedSSODiscoveryUrl)); dispatch(setSSOProviders(config.ssoProviders)); - // Check if we are in standalone mode - // const standaloneShared = localStorage.getItem('standaloneShared') == 'true'; // EDGE case: from url param it could happen that we lose the value due to SSO redirect const { standalone } = config; - // || standaloneShared; - // if a dashboard database was previously set, remember to use it. const dashboardDatabase = state.application.standaloneDashboardDatabase; + dispatch( setStandaloneEnabled( standalone, @@ -448,7 +471,6 @@ export const loadApplicationConfigThunk = () => async (dispatch: any, getState: config.skipAddDashErrorPopup ) ); - localStorage.removeItem('standaloneShared'); dispatch(setLoggingMode(config.loggingMode)); dispatch(setLoggingDatabase(config.loggingDatabase)); diff --git a/src/chart/ChartUtils.ts b/src/chart/ChartUtils.ts index 6a2911ef4..c88afe17a 100644 --- a/src/chart/ChartUtils.ts +++ b/src/chart/ChartUtils.ts @@ -164,7 +164,7 @@ export const downloadCSV = (rows) => { headers.forEach((header) => { // Parse value let value = row[header]; - if (value && 'low' in value) { + if (value && value.low) { value = value.low; } csv += `${JSON.stringify(value)}`; diff --git a/src/chart/bar/BarChart.tsx b/src/chart/bar/BarChart.tsx index cd3a5582f..132d13ecb 100644 --- a/src/chart/bar/BarChart.tsx +++ b/src/chart/bar/BarChart.tsx @@ -28,9 +28,6 @@ const NeoBarChart = (props: ChartProps) => { const padding = settings.padding ? settings.padding : 0.25; const innerPadding = settings.innerPadding ? settings.innerPadding : 0; const expandHeightForLegend = settings.expandHeightForLegend ? settings.expandHeightForLegend : false; - const displayYAxis = settings.displayYAxis ?? true; - const displayYGridLines = settings.displayYGridLines ?? true; - const actionsRules = extensionEnabled(props.extensions, 'actions') && props.settings && props.settings.actionsRules ? props.settings.actionsRules @@ -411,16 +408,11 @@ const NeoBarChart = (props: ChartProps) => { tickPadding: 5, tickRotation: labelRotation, }} - axisLeft={ - displayYAxis - ? { - tickSize: 5, - tickPadding: 5, - tickRotation: 0, - } - : null - } - enableGridY={displayYGridLines} + axisLeft={{ + tickSize: 5, + tickPadding: 5, + tickRotation: 0, + }} labelSkipWidth={labelSkipWidth} labelSkipHeight={labelSkipHeight} labelTextColor={{ from: 'color', modifiers: [['darker', 1.6]] }} diff --git a/src/chart/markdown/MarkdownChart.tsx b/src/chart/markdown/MarkdownChart.tsx index a6958edcc..d373b0da5 100644 --- a/src/chart/markdown/MarkdownChart.tsx +++ b/src/chart/markdown/MarkdownChart.tsx @@ -1,40 +1,13 @@ import React from 'react'; import { ChartProps } from '../Chart'; import ReactMarkdown from 'react-markdown'; -import remarkGfm from 'remark-gfm'; -import URI from 'urijs'; +import gfm from 'remark-gfm'; import { replaceDashboardParameters } from '../ChartUtils'; -// Sanitizes URIs -const transformUri = (uri: string): string | undefined => { - const parsedUri = URI(uri); - if (parsedUri.protocol() === 'http' || parsedUri.protocol() === 'https') { - return parsedUri.toString(); // Convert URI object back to string - } - return undefined; // Return undefined to skip rendering of potentially unsafe URLs -}; - -// Define custom components for Markdown elements -const CustomTable = ({ _, ...props }) => ; -const CustomTh = ({ _, ...props }) =>
; -const CustomTd = ({ _, ...props }) => ; -const CustomATag = ({ _, href, ...props }) => ( - // Apply URI transformation right in the anchor element for additional security - -); - /** * Renders Markdown text provided by the user. */ const NeoMarkdownChart = (props: ChartProps) => { - // Define custom components for Markdown elements - const components = { - table: CustomTable, - th: CustomTh, - td: CustomTd, - a: CustomATag, - }; - // Records are overridden to be a single element array with a field called 'input'. const { records } = props; const parameters = props.parameters ? props.parameters : {}; @@ -44,18 +17,13 @@ const NeoMarkdownChart = (props: ChartProps) => { : true; const markdown = records[0].input; const modifiedMarkdown = replaceGlobalParameters ? replaceDashboardParameters(markdown, parameters) : markdown; + // TODO: we should check if the gfm plugin has an impact on the standard security provided by ReactMarkdown return (
- - +
); }; diff --git a/src/chart/parameter/component/NodePropertyParameterSelect.tsx b/src/chart/parameter/component/NodePropertyParameterSelect.tsx index e6c1da5f7..61e9d2ba6 100644 --- a/src/chart/parameter/component/NodePropertyParameterSelect.tsx +++ b/src/chart/parameter/component/NodePropertyParameterSelect.tsx @@ -161,7 +161,7 @@ const NodePropertyParameterSelectComponent = (props: ParameterSelectProps) => { if (extraRecords && extraRecords[0] && extraRecords[0].error) { return ( ); } diff --git a/src/chart/table/TableActionsHelper.ts b/src/chart/table/TableActionsHelper.ts index 64ae5d32c..2033ab940 100644 --- a/src/chart/table/TableActionsHelper.ts +++ b/src/chart/table/TableActionsHelper.ts @@ -64,17 +64,17 @@ export const getCheckboxes = (actionsRules, rows, getGlobalParameter) => { // If the parameter is an array (to be expected), iterate over it to find the rows to check. if (Array.isArray(values)) { values.forEach((value) => { - rows.forEach((row) => { + rows.forEach((row, index) => { if (row[fieldName] == value) { - selection.push(row.id); + selection.push(index); } }); }); } else { // Else (special case), still check the row if it's a single value parameter. - rows.forEach((row) => { + rows.forEach((row, index) => { if (row[fieldName] == values) { - selection.push(row.id); + selection.push(index); } }); } @@ -84,8 +84,7 @@ export const getCheckboxes = (actionsRules, rows, getGlobalParameter) => { export const updateCheckBoxes = (actionsRules, rows, selection, setGlobalParameter) => { if (hasCheckboxes(actionsRules)) { - const selectedRows = rows.filter((row) => selection.includes(row.id)); - console.log(selectedRows); + const selectedRows = rows.filter((_, i) => selection.includes(i)); let rules = actionsRules.filter((rule) => rule.condition && rule.condition == 'rowCheck'); rules.forEach((rule) => { const parameterValues = selectedRows.map((row) => row[rule.value]).filter((v) => v !== undefined); diff --git a/src/chart/table/TableChart.tsx b/src/chart/table/TableChart.tsx index cd245b391..f632d7199 100644 --- a/src/chart/table/TableChart.tsx +++ b/src/chart/table/TableChart.tsx @@ -3,7 +3,6 @@ import { DataGrid, GridColumnVisibilityModel, GridRowId } from '@mui/x-data-grid import { ChartProps } from '../Chart'; import { evaluateRulesOnDict, - evaluateSingleRuleOnDict, generateClassDefinitionsBasedOnRules, useStyleRules, } from '../../extensions/styling/StyleRuleEvaluator'; @@ -127,6 +126,7 @@ export const NeoTableChart = (props: ChartProps) => { const useExpandedRenderer = props.settings?.expandedCellRenderer; const tableRowHeight = compact ? TABLE_ROW_HEIGHT / 2 : TABLE_ROW_HEIGHT; + const pageSizeReducer = compact ? 3 : 1; const columnWidthsType = props.settings && props.settings.columnWidthsType ? props.settings.columnWidthsType : 'Relative (%)'; @@ -266,14 +266,16 @@ export const NeoTableChart = (props: ChartProps) => { ); }); - const pageNames = getPageNumbersAndNamesList(); - const customStyles = { '&.MuiDataGrid-root .MuiDataGrid-footerContainer > div': { marginTop: '0px' } }; + const availableRowHeight = (props.dimensions.height - TABLE_HEADER_HEIGHT - TABLE_FOOTER_HEIGHT) / tableRowHeight; + const tablePageSize = compact + ? Math.round(availableRowHeight) - pageSizeReducer + : Math.floor(availableRowHeight) - pageSizeReducer; + const pageNames = getPageNumbersAndNamesList(); const commonGridProps = { key: 'tableKey', - columnHeaderHeight: 32, - rowHeight: tableRowHeight, - autoPageSize: true, + headerHeight: 32, + density: compact ? 'compact' : 'standard', rows: rows, columns: columns, columnVisibilityModel: columnVisibilityModel, @@ -289,14 +291,15 @@ export const NeoTableChart = (props: ChartProps) => { } }, checkboxSelection: hasCheckboxes(actionsRules), - rowSelectionModel: getCheckboxes(actionsRules, rows, props.getGlobalParameter), - onRowSelectionModelChange: (selection) => updateCheckBoxes(actionsRules, rows, selection, props.setGlobalParameter), - disableRowSelectionOnClick: true, + selectionModel: getCheckboxes(actionsRules, rows, props.getGlobalParameter), + onSelectionModelChange: (selection) => updateCheckBoxes(actionsRules, rows, selection, props.setGlobalParameter), + pageSize: tablePageSize > 0 ? tablePageSize : 5, + rowsPerPageOptions: rows.length < 5 ? [rows.length, 5] : [5], + disableSelectionOnClick: true, components: { ColumnSortedDescendingIcon: () => <>, ColumnSortedAscendingIcon: () => <>, }, - // TODO: if mixing and matching row and cell styling, row rules MUST be set first or will not populate correctly getRowClassName: (params) => { return ['row color', 'row text color'] .map((e) => { @@ -307,21 +310,7 @@ export const NeoTableChart = (props: ChartProps) => { getCellClassName: (params) => { return ['cell color', 'cell text color'] .map((e) => { - let trueRulesList = ['']; - let trueRule; - for (const [index, rule] of styleRules.entries()) { - if (rule.targetField) { - if (rule.targetField === params.field) { - trueRule = `rule${evaluateSingleRuleOnDict({ [rule.field]: params.row[rule.field] }, rule, index, [ - e, - ])}`; - } - } else { - trueRule = `rule${evaluateSingleRuleOnDict({ [params.field]: params.value }, rule, index, [e])}`; - } - trueRulesList.push(trueRule); - } - return trueRulesList.join(' '); + return `rule${evaluateRulesOnDict({ [params.field]: params.value }, styleRules, [e])}`; }) .join(' '); }, diff --git a/src/config/ReportConfig.tsx b/src/config/ReportConfig.tsx index 1a803f41a..621dc5a95 100644 --- a/src/config/ReportConfig.tsx +++ b/src/config/ReportConfig.tsx @@ -476,18 +476,6 @@ const _REPORT_TYPES = { type: SELECTION_TYPES.NUMBER, default: 0.25, }, - displayYAxis: { - label: 'Display Y axis', - type: SELECTION_TYPES.LIST, - values: [true, false], - default: true, - }, - displayYGridLines: { - label: 'Display Y grid lines', - type: SELECTION_TYPES.LIST, - values: [true, false], - default: true, - }, description: { label: 'Report Description', type: SELECTION_TYPES.MULTILINE_TEXT, diff --git a/src/extensions/rbac/RBACManagementModal.tsx b/src/extensions/rbac/RBACManagementModal.tsx index a69e211bc..f3f17a08c 100644 --- a/src/extensions/rbac/RBACManagementModal.tsx +++ b/src/extensions/rbac/RBACManagementModal.tsx @@ -32,7 +32,6 @@ export const RBACManagementModal = ({ open, handleClose, currentRole, createNoti const [allowCompleted, setAllowCompleted] = useState(false); const [usersCompleted, setUsersCompleted] = useState(false); const [failed, setFailed] = useState(false); - const [isDatabaseEmpty, setIsDatabaseEmpty] = useState(false); useEffect(() => { if (!open) { @@ -76,48 +75,35 @@ export const RBACManagementModal = ({ open, handleClose, currentRole, createNoti const handleDatabaseSelect = (selectedOption) => { setSelectedDatabase(selectedOption.value); - setLabels([]); - setAllowList([]); - setDenyList([]); - retrieveLabelsList(driver, selectedOption.value, (records) => { - if (records.length === 0) { - setIsDatabaseEmpty(true); - } else { - parseLabelsList(selectedOption.value, records); - setIsDatabaseEmpty(false); - } - }); + retrieveLabelsList(driver, selectedOption.value, (records) => parseLabelsList(selectedOption.value, records)); }; const handleSave = async () => { createNotification('Updating', `Access for role '${currentRole}' is being updated, please wait...`); - try { - await updateUsers( + console.log(selectedUsers); + updateUsers( + driver, + currentRole, + neo4jUsers, + selectedUsers, + () => setUsersCompleted(true), + (failReason) => setFailed(`Operation 'ROLE-USER ASSIGNMENT' failed.\n Reason: ${failReason}`) + ); + + if (selectedDatabase) { + const nonFixedDenyList = denyList.filter((n) => !fixedDenyList.includes(n)); + const nonFixedAllowList = allowList.filter((n) => !fixedDenyList.includes(n)); + updatePrivileges( driver, + selectedDatabase, currentRole, - neo4jUsers, - selectedUsers, - () => setUsersCompleted(true), - (failReason) => setFailed(`Operation 'ROLE-USER ASSIGNMENT' failed.\n Reason: ${failReason}`) - ); - - if (selectedDatabase && labels.length > 0) { - // Check if there are labels to update - const nonFixedDenyList = denyList.filter((n) => !fixedDenyList.includes(n)); - const nonFixedAllowList = allowList.filter((n) => !fixedDenyList.includes(n)); - - await updatePrivileges( - driver, - selectedDatabase, - currentRole, - labels, - nonFixedDenyList, - Operation.DENY, - () => setDenyCompleted(true), - (failReason) => setFailed(`Operation 'DENY LABEL ACCESS' failed.\n Reason: ${failReason}`) - ); - - await updatePrivileges( + labels, + nonFixedDenyList, + Operation.DENY, + () => setDenyCompleted(true), + (failReason) => setFailed(`Operation 'DENY LABEL ACCESS' failed.\n Reason: ${failReason}`) + ).then(() => { + updatePrivileges( driver, selectedDatabase, currentRole, @@ -127,18 +113,14 @@ export const RBACManagementModal = ({ open, handleClose, currentRole, createNoti () => setAllowCompleted(true), (failReason) => setFailed(`Operation 'ALLOW LABEL ACCESS' failed.\n Reason: ${failReason}`) ); - } else { - // Since there is no database or labels selected, we don't run the DENY/ALLOW queries. - // We just mark them as completed so the success message shows up. - setDenyCompleted(true); - setAllowCompleted(true); - } - } catch (error) { - // Handle any errors that occur during the update process - createNotification('error', `An error occurred: ${error.message}`); - } finally { - handleClose(); + }); + } else { + // Since there is no database selected, we don't run the DENY/ALLOW queries. + // We just mark them as completed so the success message shows up. + setDenyCompleted(true); + setAllowCompleted(true); } + handleClose(); }; return ( @@ -189,13 +171,8 @@ export const RBACManagementModal = ({ open, handleClose, currentRole, createNoti onChange: handleDatabaseSelect, }} /> - {selectedDatabase && isDatabaseEmpty && ( -

- This database is currently empty. Please select a different database or add labels to manage access. -

- )} - {selectedDatabase && !isDatabaseEmpty && loaded && ( + {selectedDatabase && loaded && ( <>
diff --git a/src/extensions/rbac/RBACUtils.ts b/src/extensions/rbac/RBACUtils.ts index 6fc56d375..c93d54e56 100644 --- a/src/extensions/rbac/RBACUtils.ts +++ b/src/extensions/rbac/RBACUtils.ts @@ -217,24 +217,15 @@ export const retrieveNeo4jUsers = (driver, currentRole, setNeo4jUsers, setRoleUs * @param setLabels callback to update the list of labels. */ export function retrieveLabelsList(driver, database: any, setLabels: (records: any) => void) { - let labelsSet = false; // Flag to track if setLabels was called - - // Wrapper around the original setLabels to set the flag when called - const wrappedSetLabels = (records) => { - labelsSet = true; - setLabels(records); - }; - - runCypherQuery(driver, database, 'CALL db.labels()', {}, 1000, () => {}, wrappedSetLabels) - .then(() => { - if (!labelsSet) { - setLabels([]); - } - }) - .catch((error) => { - console.error('Error retrieving labels:', error); - setLabels([]); - }); + runCypherQuery( + driver, + database.value, + 'CALL db.labels()', + {}, + 1000, + () => {}, + (records) => setLabels(records) + ); } /** @@ -274,31 +265,8 @@ export async function updateUsers(driver, currentRole, allUsers, selectedUsers, `REVOKE ROLE ${currentRole} FROM ${escapedAllUsers}`, {}, 1000, - async (status) => { + (status) => { globalStatus = status; - if (globalStatus == QueryStatus.NO_DATA || globalStatus == QueryStatus.COMPLETE) { - // TODO: Neo4j is very slow in updating after the previous query, even though it is technically a finished query. - // We build in an artificial delay... This must be improved the future. - setTimeout(async () => { - if (selectedUsers.length > 0) { - const escapedSelectedUsers = selectedUsers.map((user) => `\`${user}\``).join(','); - await runCypherQuery( - driver, - 'system', - `GRANT ROLE ${currentRole} TO ${escapedSelectedUsers};`, - {}, - 1000, - (status) => { - if (status == QueryStatus.NO_DATA || QueryStatus.COMPLETE) { - onSuccess(); - } - } - ); - } else { - onSuccess(); - } - }, 2000); - } }, (records) => { if (records && records[0] && records[0].error) { @@ -306,4 +274,25 @@ export async function updateUsers(driver, currentRole, allUsers, selectedUsers, } } ); + if (globalStatus == QueryStatus.NO_DATA || globalStatus == QueryStatus.COMPLETE) { + // TODO: Neo4j is very slow in updating after the previous query, even though it is technically a finished query. + // We build in an artificial delay... + if (selectedUsers.length > 0) { + const escapedSelectedUsers = selectedUsers.map((user) => `\`${user}\``).join(','); + await runCypherQuery( + driver, + 'system', + `GRANT ROLE ${currentRole} TO ${escapedSelectedUsers}`, + {}, + 1000, + (status) => { + if (status == QueryStatus.NO_DATA || QueryStatus.COMPLETE) { + onSuccess(); + } + } + ); + } else { + onSuccess(); + } + } } diff --git a/src/extensions/styling/StyleRuleCreationModal.tsx b/src/extensions/styling/StyleRuleCreationModal.tsx index a295044d5..0c26c4746 100644 --- a/src/extensions/styling/StyleRuleCreationModal.tsx +++ b/src/extensions/styling/StyleRuleCreationModal.tsx @@ -338,35 +338,6 @@ export const NeoCustomReportStyleModal = ({ }} fluid /> - - e.toLowerCase().includes(rule.targetField) - )} - value={rule.targetField ? rule.targetField : (rule.field ? rule.field : '')} - inputValue={rule.targetField ? rule.targetField : (rule.field ? rule.field : '')} - popupIcon={<>} - style={{ minWidth: 125, visibility: rule.customization.includes("cell") ? 'visible' : 'hidden', display: rule.customization.includes("cell") ? '' : 'none' }} - onInputChange={(event, value) => { - updateRuleField(index, 'targetField', value); - }} - onChange={(event, newValue) => { - updateRuleField(index, 'targetField', newValue); - }} - renderInput={(params) => ( - - )} - /> div { - @apply n-mt-0; - } - /* Make bullet list points in Markdown card view */ .card-view ul { @apply n-list-disc n-ml-token-7; @@ -103,22 +98,4 @@ .n-bg-dark-neutral-text-weak { background-color: rgb(196 200 205 / var(--tw-bg-opacity)) !important; } - - /* Markdown table styles */ - .markdown-table { - width: 100%; - border-collapse: collapse; - } - - .markdown-table th, - .markdown-table td { - border: 1px solid #ddd; /* Light gray border */ - padding: 8px; /* Padding around text */ - text-align: left; /* Align text to the left */ - } - - .markdown-table th { - background-color: #f4f4f4; /* Light gray background for header */ - color: #333; /* Dark text color for contrast */ - } } diff --git a/src/modal/AboutModal.tsx b/src/modal/AboutModal.tsx index 62d4816c0..f7d8e40c1 100644 --- a/src/modal/AboutModal.tsx +++ b/src/modal/AboutModal.tsx @@ -3,7 +3,7 @@ import { Button, Dialog, TextLink } from '@neo4j-ndl/react'; import { BookOpenIconOutline, BeakerIconOutline } from '@neo4j-ndl/react/icons'; import { Section, SectionTitle, SectionContent } from './ModalUtils'; -export const version = '2.4.9-labs'; +export const version = '2.4.8'; export const NeoAboutModal = ({ open, handleClose, getDebugState }) => { const downloadDebugFile = () => { diff --git a/src/report/ReportRecordProcessing.tsx b/src/report/ReportRecordProcessing.tsx index 402f85524..2e51213fa 100644 --- a/src/report/ReportRecordProcessing.tsx +++ b/src/report/ReportRecordProcessing.tsx @@ -269,17 +269,16 @@ function RenderArray(value, transposedTable = false) { mapped = value.map((v, i) => { return RenderSubValue(v) + (i < value.length - 1 ? ', ' : ''); }); - } else { - // Render Node and Relationship objects, which will look like a Path - mapped = value.map((v, i) => { - return ( - - {RenderSubValue(v)} - {i < value.length - 1 && !valueIsNode(v) && !valueIsRelationship(v) ? , : <>} - - ); - }); } + // Render Node and Relationship objects, which will look like a Path + mapped = value.map((v, i) => { + return ( + + {RenderSubValue(v)} + {i < value.length - 1 && !valueIsNode(v) && !valueIsRelationship(v) ? , : <>} + + ); + }); return mapped; } diff --git a/src/utils/parameterUtils.ts b/src/utils/parameterUtils.ts index 62d8a1c89..4a9a60eb8 100644 --- a/src/utils/parameterUtils.ts +++ b/src/utils/parameterUtils.ts @@ -1,39 +1,22 @@ -/** - * Extracts all parameter names from a given Cypher query string. - * - * @param {string} cypherQuery The Cypher query string to extract parameter names from. - * @returns {string[]} An array containing all extracted parameter names. - */ -export const extractAllParameterNames = (cypherQuery: string): string[] => { - // A regular expression pattern to match parameter names following '$' - const pattern = /\$([A-Za-z_]\w*)/g; +export const extractAllParameterNames = (cypherQuery) => { + // A regular expression pattern to match parameter names following '$' + const pattern = /\$([A-Za-z_]\w*)/g; - const parameterNames: string[] = []; - let match: any; + const parameterNames: string[] = []; + let match: any; - while ((match = pattern.exec(cypherQuery)) !== null) { - parameterNames.push(match[1]); - } + while ((match = pattern.exec(cypherQuery)) !== null) { + parameterNames.push(match[1]); + } - return parameterNames; -}; + return parameterNames; +} -/** - * Checks if all parameter names are present in the global parameter names. - * - * @param {string[]} parameterNames An array of parameter names to be checked. - * @param {object} globalParameterNames The object containing global parameter names to compare against. - * @returns {boolean} A boolean indicating whether all parameters are present in the global parameters. - */ export const checkParametersNameInGlobalParameter = (parameterNames: string[], globalParameterNames: any): boolean => { - for (const key of parameterNames) { - if ( - !globalParameterNames[key] || - (Array.isArray(globalParameterNames[key]) && globalParameterNames[key].length === 0) || - globalParameterNames[key] === '' - ) { - return true; + for (const key of parameterNames) { + if (!globalParameterNames[key] || (Array.isArray(globalParameterNames[key]) && globalParameterNames[key].length === 0) || globalParameterNames[key] === '') { + return true; + } } - } - return false; -}; + return false; +} \ No newline at end of file diff --git a/ssl/Dockerfile b/ssl/Dockerfile deleted file mode 100644 index 3e362b4de..000000000 --- a/ssl/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# build stage -FROM neo4jlabs/neodash:latest AS neodash - -ENV NGINX_HTTPS_PORT=5443 - -USER root - -RUN mkdir -p /etc/nginx/certs - -RUN --mount=type=secret,id=NEODASH_SSL_KEY \ - base64 -d /run/secrets/NEODASH_SSL_KEY > /etc/nginx/certs/key.pem - -RUN --mount=type=secret,id=NEODASH_SSL_CERT \ - base64 -d /run/secrets/NEODASH_SSL_CERT > /etc/nginx/certs/cert.pem - -COPY default.conf /etc/nginx/templates/default.conf.template -COPY default.conf /etc/nginx/conf.d/ - -RUN chown -R nginx:nginx /etc/nginx - -USER nginx -EXPOSE $NGINX_HTTPS_PORT - -HEALTHCHECK CMD curl --fail "https://localhost:$NGINX_HTTPS_PORT" || exit 1 -LABEL version="1.0" \ No newline at end of file diff --git a/ssl/default.conf b/ssl/default.conf deleted file mode 100644 index 547c4b214..000000000 --- a/ssl/default.conf +++ /dev/null @@ -1,34 +0,0 @@ -server { - listen ${NGINX_PORT}; - server_name localhost; - include mime.types; - location / { - root /usr/share/nginx/html; - try_files $uri $uri/ /index.html; - index index.html index.htm; - } - # redirect server error pages to the static page /50x.html - # Note: This is optional, depending on the implementation in React - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /usr/share/nginx/html; - } -} -server { - listen 5443 ssl; - ssl_certificate /etc/nginx/certs/cert.pem; - ssl_certificate_key /etc/nginx/certs/key.pem; - server_name localhost; - include mime.types; - location / { - root /usr/share/nginx/html; - try_files $uri $uri/ /index.html; - index index.html index.htm; - } - # redirect server error pages to the static page /50x.html - # Note: This is optional, depending on the implementation in React - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /usr/share/nginx/html; - } -} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 1e34ce1ee..2cb455b53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1313,13 +1313,6 @@ dependencies: regenerator-runtime "^0.14.0" -"@babel/runtime@^7.24.0": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.5.tgz#230946857c053a36ccc66e1dd03b17dd0c4ed02c" - integrity sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g== - dependencies: - regenerator-runtime "^0.14.0" - "@babel/template@^7.18.10", "@babel/template@^7.20.7": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" @@ -2332,42 +2325,23 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" - integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - "@jridgewell/resolve-uri@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/source-map@^0.3.3": - version "0.3.6" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" - integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" "@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" @@ -2379,10 +2353,13 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/sourcemap-codec@^1.4.14": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" - integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== +"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.8", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" "@jridgewell/trace-mapping@^0.3.17": version "0.3.18" @@ -2392,22 +2369,6 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@jridgewell/trace-mapping@^0.3.8", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.17" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" - integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== - dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" - "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" @@ -2510,15 +2471,6 @@ "@mui/utils" "^5.15.11" prop-types "^15.8.1" -"@mui/private-theming@^5.15.14": - version "5.15.14" - resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.15.14.tgz#edd9a82948ed01586a01c842eb89f0e3f68970ee" - integrity sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw== - dependencies: - "@babel/runtime" "^7.23.9" - "@mui/utils" "^5.15.14" - prop-types "^15.8.1" - "@mui/styled-engine@^5.15.11": version "5.15.11" resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.15.11.tgz#040181f31910e0f66d43a5c44fe89da06b34212b" @@ -2529,16 +2481,6 @@ csstype "^3.1.3" prop-types "^15.8.1" -"@mui/styled-engine@^5.15.14": - version "5.15.14" - resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.15.14.tgz#168b154c4327fa4ccc1933a498331d53f61c0de2" - integrity sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw== - dependencies: - "@babel/runtime" "^7.23.9" - "@emotion/cache" "^11.11.0" - csstype "^3.1.3" - prop-types "^15.8.1" - "@mui/styles@^5.12.3": version "5.15.11" resolved "https://registry.yarnpkg.com/@mui/styles/-/styles-5.15.11.tgz#2fc57a42eff47542924e1ba90fb188b733d295aa" @@ -2576,30 +2518,11 @@ csstype "^3.1.3" prop-types "^15.8.1" -"@mui/system@^5.15.14": - version "5.15.15" - resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.15.15.tgz#658771b200ce3c4a0f28e58169f02e5e718d1c53" - integrity sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ== - dependencies: - "@babel/runtime" "^7.23.9" - "@mui/private-theming" "^5.15.14" - "@mui/styled-engine" "^5.15.14" - "@mui/types" "^7.2.14" - "@mui/utils" "^5.15.14" - clsx "^2.1.0" - csstype "^3.1.3" - prop-types "^15.8.1" - "@mui/types@^7.2.13": version "7.2.13" resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.13.tgz#d1584912942f9dc042441ecc2d1452be39c666b8" integrity sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g== -"@mui/types@^7.2.14": - version "7.2.14" - resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.14.tgz#8a02ac129b70f3d82f2f9b76ded2c8d48e3fc8c9" - integrity sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ== - "@mui/utils@^5.10.3": version "5.11.9" resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.11.9.tgz#8fab9cf773c63ad916597921860d2344b5d4b706" @@ -2621,27 +2544,16 @@ prop-types "^15.8.1" react-is "^18.2.0" -"@mui/utils@^5.15.14": - version "5.15.14" - resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.15.14.tgz#e414d7efd5db00bfdc875273a40c0a89112ade3a" - integrity sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA== - dependencies: - "@babel/runtime" "^7.23.9" - "@types/prop-types" "^15.7.11" - prop-types "^15.8.1" - react-is "^18.2.0" - -"@mui/x-data-grid@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@mui/x-data-grid/-/x-data-grid-7.4.0.tgz#1901f2908aca760146ccae74b064fc15462bcf63" - integrity sha512-ILu0AVqqHQf4wN/nblsJ/k7PkvlB115vQ/FEiYk7neZlc/kOJOUyst3MWMVClAecZ8+JEs476q40xd4r1CtMfw== +"@mui/x-data-grid@5.17.26": + version "5.17.26" + resolved "https://registry.yarnpkg.com/@mui/x-data-grid/-/x-data-grid-5.17.26.tgz#1f7fa73dd3986cf052e2fd2cb56eb4678a7bd913" + integrity sha512-eGJq9J0g9cDGLFfMmugOadZx0mJeOd/yQpHwEa5gUXyONS6qF0OhXSWyDOhDdA3l2TOoQzotMN5dY/T4Wl1KYA== dependencies: - "@babel/runtime" "^7.24.0" - "@mui/system" "^5.15.14" - "@mui/utils" "^5.15.14" - clsx "^2.1.1" + "@babel/runtime" "^7.18.9" + "@mui/utils" "^5.10.3" + clsx "^1.2.1" prop-types "^15.8.1" - reselect "^4.1.8" + reselect "^4.1.6" "@mui/x-date-pickers@^5.0.17": version "5.0.19" @@ -4606,10 +4518,31 @@ dependencies: "@types/ms" "*" -"@types/estree@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== +"@types/eslint-scope@^3.7.3": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.21.1" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.21.1.tgz#110b441a210d53ab47795124dbc3e9bb993d1e7c" + integrity sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + +"@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": version "4.17.33" @@ -4689,7 +4622,7 @@ resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.7.tgz#226a9e31680835a6188e887f3988e60c04d3f6a3" integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA== -"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== @@ -4993,125 +4926,125 @@ "@typescript-eslint/types" "5.52.0" eslint-visitor-keys "^3.3.0" -"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" - integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== +"@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== dependencies: - "@webassemblyjs/helper-numbers" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" -"@webassemblyjs/floating-point-hex-parser@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" - integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== +"@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== -"@webassemblyjs/helper-api-error@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" - integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== +"@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== -"@webassemblyjs/helper-buffer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" - integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== +"@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== -"@webassemblyjs/helper-numbers@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" - integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== +"@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.6" - "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-wasm-bytecode@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" - integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== +"@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== -"@webassemblyjs/helper-wasm-section@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" - integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== +"@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" -"@webassemblyjs/ieee754@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" - integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== +"@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" - integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== +"@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" - integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== - -"@webassemblyjs/wasm-edit@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" - integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/helper-wasm-section" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-opt" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - "@webassemblyjs/wast-printer" "1.12.1" - -"@webassemblyjs/wasm-gen@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" - integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wasm-opt@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" - integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - -"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" - integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-api-error" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wast-printer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" - integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== - dependencies: - "@webassemblyjs/ast" "1.12.1" +"@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + +"@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + +"@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + +"@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" "@webpack-cli/configtest@^1.2.0": @@ -5164,20 +5097,25 @@ accessor-fn@1: resolved "https://registry.yarnpkg.com/accessor-fn/-/accessor-fn-1.4.1.tgz#ff6555ba91bbae1ba8e469bfdca6e7ee74dccc78" integrity sha512-P7yNKfmpuWLUwiRVk9RkRIPGjngemjZ7yANc0DL7otgDqEIWkEByMhShzfgQ5ZwCPEUmba4v1kOqCdGhpzY3ew== -acorn-import-attributes@^1.9.5: - version "1.9.5" - resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" - integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== +acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.7.1, acorn@^8.8.0, acorn@^8.8.1, acorn@^8.8.2: - version "8.12.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" - integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== +acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.0: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +acorn@^8.8.1: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== agent-base@6: version "6.0.2" @@ -5701,15 +5639,25 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.21.10, browserslist@^4.21.3, browserslist@^4.21.5, browserslist@^4.21.9: - version "4.23.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.3.tgz#debb029d3c93ebc97ffbc8d9cbb03403e227c800" - integrity sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA== +browserslist@^4.14.5, browserslist@^4.21.3, browserslist@^4.21.5: + version "4.21.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" + integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== dependencies: - caniuse-lite "^1.0.30001646" - electron-to-chromium "^1.5.4" - node-releases "^2.0.18" - update-browserslist-db "^1.1.0" + caniuse-lite "^1.0.30001449" + electron-to-chromium "^1.4.284" + node-releases "^2.0.8" + update-browserslist-db "^1.0.10" + +browserslist@^4.21.9: + version "4.21.9" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.9.tgz#e11bdd3c313d7e2a9e87e8b4b0c7872b13897635" + integrity sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg== + dependencies: + caniuse-lite "^1.0.30001503" + electron-to-chromium "^1.4.431" + node-releases "^2.0.12" + update-browserslist-db "^1.0.11" buffer-alloc-unsafe@^1.1.0: version "1.1.0" @@ -5831,16 +5779,11 @@ camelize@^1.0.0: resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3" integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== -caniuse-lite@^1.0.30001464: +caniuse-lite@^1.0.30001449, caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001503: version "1.0.30001546" resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001546.tgz" integrity sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw== -caniuse-lite@^1.0.30001646: - version "1.0.30001655" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz#0ce881f5a19a2dcfda2ecd927df4d5c1684b982f" - integrity sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg== - canvas-color-tracker@1: version "1.2.1" resolved "https://registry.yarnpkg.com/canvas-color-tracker/-/canvas-color-tracker-1.2.1.tgz#c552872f8f254bac3e74ea4cc7fed3bb19859bf1" @@ -6074,11 +6017,6 @@ clsx@^2.1.0: resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.0.tgz#e851283bcb5c80ee7608db18487433f7b23f77cb" integrity sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg== -clsx@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" - integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== - color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -7209,10 +7147,15 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.5.4: - version "1.5.13" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz#1abf0410c5344b2b829b7247e031f02810d442e6" - integrity sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q== +electron-to-chromium@^1.4.284: + version "1.4.352" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.352.tgz#be96bd7c2f4b980deebc9338a49a67430a33ed73" + integrity sha512-ikFUEyu5/q+wJpMOxWxTaEVk2M1qKqTGKKyfJmod1CPZxKfYnxVS41/GCBQg21ItBpZybyN8sNpRqCUGm+Zc4Q== + +electron-to-chromium@^1.4.431: + version "1.4.450" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.450.tgz#df232c961ee9bf4e8980f86e96a6e9f291720138" + integrity sha512-BLG5HxSELlrMx7dJ2s+8SFlsCtJp37Zpk2VAxyC6CZtbc+9AJeZHfYHbrlSgdXp6saQ8StMqOTEDaBKgA7u1sw== emoji-regex@^8.0.0: version "8.0.0" @@ -7241,10 +7184,10 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^5.17.1: - version "5.17.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" - integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== +enhanced-resolve@^5.10.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" + integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -7320,10 +7263,10 @@ es-get-iterator@^1.1.2: isarray "^2.0.5" stop-iteration-iterator "^1.0.0" -es-module-lexer@^1.2.1: - version "1.5.4" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" - integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== es-shim-unscopables@^1.0.0: version "1.0.0" @@ -7395,10 +7338,10 @@ es6-weak-map@^2.0.3: es6-iterator "^2.0.3" es6-symbol "^3.1.1" -escalade@^3.1.2: - version "3.2.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" - integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-html@~1.0.3: version "1.0.3" @@ -8092,9 +8035,9 @@ focus-lock@^0.11.6: tslib "^2.0.3" follow-redirects@^1.0.0, follow-redirects@^1.14.8: - version "1.15.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" - integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + version "1.15.4" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.4.tgz#cdc7d308bf6493126b17ea2191ea0ccf3e535adf" + integrity sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw== for-each@^0.3.3: version "0.3.3" @@ -8438,7 +8381,12 @@ got@^11.8.5: p-cancelable "^2.0.0" responselike "^2.0.0" -graceful-fs@^4.1.10, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.10, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +graceful-fs@^4.1.15: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -10632,10 +10580,15 @@ node-preload@^0.2.1: dependencies: process-on-spawn "^1.0.0" -node-releases@^2.0.18: - version "2.0.18" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" - integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== +node-releases@^2.0.12: + version "2.0.12" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039" + integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ== + +node-releases@^2.0.8: + version "2.0.10" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" + integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" @@ -11067,11 +11020,6 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picocolors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== - picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.0, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" @@ -12255,7 +12203,7 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== -reselect@^4.1.8: +reselect@^4.1.6, reselect@^4.1.8: version "4.1.8" resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== @@ -12447,10 +12395,10 @@ schema-utils@^2.6.5, schema-utils@^2.7.0: ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" - integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== +schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== dependencies: "@types/json-schema" "^7.0.8" ajv "^6.12.5" @@ -12526,10 +12474,10 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" -serialize-javascript@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" - integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== +serialize-javascript@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" + integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== dependencies: randombytes "^2.1.0" @@ -13146,24 +13094,24 @@ tar-stream@^1.5.2: to-buffer "^1.1.1" xtend "^4.0.0" -terser-webpack-plugin@^5.3.10: - version "5.3.10" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" - integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== +terser-webpack-plugin@^5.1.3: + version "5.3.6" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" + integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== dependencies: - "@jridgewell/trace-mapping" "^0.3.20" + "@jridgewell/trace-mapping" "^0.3.14" jest-worker "^27.4.5" schema-utils "^3.1.1" - serialize-javascript "^6.0.1" - terser "^5.26.0" + serialize-javascript "^6.0.0" + terser "^5.14.1" -terser@^5.26.0: - version "5.31.6" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.6.tgz#c63858a0f0703988d0266a82fcbf2d7ba76422b1" - integrity sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg== +terser@^5.14.1: + version "5.16.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.3.tgz#3266017a9b682edfe019b8ecddd2abaae7b39c6b" + integrity sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q== dependencies: - "@jridgewell/source-map" "^0.3.3" - acorn "^8.8.2" + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" commander "^2.20.0" source-map-support "~0.5.20" @@ -13593,13 +13541,21 @@ untildify@^4.0.0: resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== -update-browserslist-db@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" - integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== +update-browserslist-db@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +update-browserslist-db@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" + integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== dependencies: - escalade "^3.1.2" - picocolors "^1.0.1" + escalade "^3.1.1" + picocolors "^1.0.0" uri-js@^4.2.2: version "4.4.1" @@ -13608,11 +13564,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urijs@^1.19.11: - version "1.19.11" - resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" - integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== - url-parse@^1.5.3: version "1.5.10" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" @@ -13724,10 +13675,10 @@ warning@^4.0.2: dependencies: loose-envify "^1.0.0" -watchpack@^2.4.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da" - integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw== +watchpack@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -13834,32 +13785,33 @@ webpack-virtual-modules@^0.5.0: integrity sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw== webpack@^5.77.0: - version "5.94.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.94.0.tgz#77a6089c716e7ab90c1c67574a28da518a20970f" - integrity sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg== - dependencies: - "@types/estree" "^1.0.5" - "@webassemblyjs/ast" "^1.12.1" - "@webassemblyjs/wasm-edit" "^1.12.1" - "@webassemblyjs/wasm-parser" "^1.12.1" + version "5.77.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.77.0.tgz#dea3ad16d7ea6b84aa55fa42f4eac9f30e7eb9b4" + integrity sha512-sbGNjBr5Ya5ss91yzjeJTLKyfiwo5C628AFjEa6WSXcZa4E+F57om3Cc8xLb1Jh0b243AWuSYRf3dn7HVeFQ9Q== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" acorn "^8.7.1" - acorn-import-attributes "^1.9.5" - browserslist "^4.21.10" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.17.1" - es-module-lexer "^1.2.1" + enhanced-resolve "^5.10.0" + es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" - graceful-fs "^4.2.11" + graceful-fs "^4.2.9" json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.2.0" + schema-utils "^3.1.0" tapable "^2.1.1" - terser-webpack-plugin "^5.3.10" - watchpack "^2.4.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.4.0" webpack-sources "^3.2.3" websocket-driver@>=0.5.1, websocket-driver@^0.7.4: @@ -13981,9 +13933,9 @@ write-file-atomic@^4.0.2: signal-exit "^3.0.7" ws@^8.4.2: - version "8.17.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" - integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + version "8.12.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.1.tgz#c51e583d79140b5e42e39be48c934131942d4a8f" + integrity sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew== xtend@^4.0.0: version "4.0.2"