From 0ffea24e130f09c4805ef6548f99bed9db71075d Mon Sep 17 00:00:00 2001 From: Alexander Ciesielski Date: Wed, 19 Oct 2022 09:11:04 +0200 Subject: [PATCH] feat(graph): toggle visibility of all projects in a folder Adds a button next to the folder label to quickly show/hide all projects of that folder ISSUES CLOSED: 12640 --- graph/client-e2e/src/integration/app.spec.ts | 18 +++++++- graph/client-e2e/src/support/app.po.ts | 3 ++ graph/client/src/app/sidebar/project-list.tsx | 41 ++++++++++++++++--- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/graph/client-e2e/src/integration/app.spec.ts b/graph/client-e2e/src/integration/app.spec.ts index d5f732941b41a4..6d15e2458f07aa 100644 --- a/graph/client-e2e/src/integration/app.spec.ts +++ b/graph/client-e2e/src/integration/app.spec.ts @@ -12,12 +12,13 @@ import { getSelectProjectsMessage, getTextFilterInput, getTextFilterReset, + getToggleAllButtonForFolder, getUncheckedProjectItems, getUnfocusProjectButton, } from '../support/app.po'; -import * as nxExamplesJson from '../fixtures/nx-examples.json'; import * as affectedJson from '../fixtures/affected.json'; +import * as nxExamplesJson from '../fixtures/nx-examples.json'; describe('graph-client', () => { before(() => { @@ -229,6 +230,21 @@ describe('graph-client', () => { }); }); + describe('toggle all projects in folder button', () => { + it('should uncheck all projects in folder if at least one project checked', () => { + cy.contains('shared-product-state').scrollIntoView().should('be.visible'); + cy.get('[data-project="shared-product-state"]').should('be.visible'); + cy.get('[data-project="shared-product-state"]').click({ force: true }); + getToggleAllButtonForFolder('shared/product').click({ force: true }); + getCheckedProjectItems().should('have.length', 0); + }); + + it('should check all projects in folder if no projects checked yet', () => { + getToggleAllButtonForFolder('shared').click({ force: true }); + getCheckedProjectItems().should('have.length', 5); + }); + }); + describe('image download button', () => { it('should be hidden initally', () => { getImageDownloadButton().should('have.class', 'opacity-0'); diff --git a/graph/client-e2e/src/support/app.po.ts b/graph/client-e2e/src/support/app.po.ts index 25d230a03fdc37..33c5a80199d6a7 100644 --- a/graph/client-e2e/src/support/app.po.ts +++ b/graph/client-e2e/src/support/app.po.ts @@ -32,3 +32,6 @@ export const getImageDownloadButton = () => export const getFocusButtonForProject = (projectName: string) => cy.get(`[data-cy="focus-button-${projectName}"]`); + +export const getToggleAllButtonForFolder = (folderName: string) => + cy.get(`[data-cy="toggle-folder-visibility-button-${folderName}"]`); diff --git a/graph/client/src/app/sidebar/project-list.tsx b/graph/client/src/app/sidebar/project-list.tsx index e88736e3d41c51..9c312569356970 100644 --- a/graph/client/src/app/sidebar/project-list.tsx +++ b/graph/client/src/app/sidebar/project-list.tsx @@ -4,9 +4,12 @@ import { MapPinIcon, } from '@heroicons/react/24/outline'; // nx-ignore-next-line +import { EyeIcon } from '@heroicons/react/24/outline'; import type { ProjectGraphNode } from '@nrwl/devkit'; +import ExperimentalFeature from '../experimental-feature'; import { useDepGraphService } from '../hooks/use-dep-graph'; import { useDepGraphSelector } from '../hooks/use-dep-graph-selector'; +import { TracingAlgorithmType } from '../machines/interfaces'; import { allProjectsSelector, getTracingInfo, @@ -14,9 +17,6 @@ import { workspaceLayoutSelector, } from '../machines/selectors'; import { parseParentDirectoriesFromFilePath } from '../util'; -import { TracingAlgorithmType } from '../machines/interfaces'; -import ExperimentalFeature from '../experimental-feature'; -import { EyeIcon } from '@heroicons/react/24/outline'; function getProjectsByType(type: string, projects: ProjectGraphNode[]) { return projects @@ -187,12 +187,41 @@ function SubProjectList({ } } + function toggleAllProjects(currentlySelected: boolean) { + if (currentlySelected) { + projects.forEach((project) => + deselectProject(project.projectGraphNode.name) + ); + } else { + projects.forEach((project) => + selectProject(project.projectGraphNode.name) + ); + } + } + + const someProjectsSelected = projects.some((project) => project.isSelected); + return ( <> {headerText !== '' ? ( -

- {headerText} -

+
+

+ {headerText} +

+ + toggleAllProjects(someProjectsSelected)} + > + + +
) : null}