From 4c42f6fd71184fbc8ac764dfcc1c8ef058dcc607 Mon Sep 17 00:00:00 2001
From: Alf Eaton <75253002+aeaton-overleaf@users.noreply.github.com>
Date: Thu, 10 Dec 2020 11:15:05 +0000
Subject: [PATCH] Merge pull request #3443 from overleaf/ta-file-tree-noselect
[ReactFileTree] Show Create Actions When No Entities Are Selected
GitOrigin-RevId: b98146fe83ce72b3122e8c8905c864a2fd73c5ad
---
.../contexts/file-tree-actionable.js | 30 +++++++++++++------
.../components/file-tree-toolbar.test.js | 9 ++++--
.../file-tree/flows/create-folder.test.js | 3 +-
3 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/services/web/frontend/js/features/file-tree/contexts/file-tree-actionable.js b/services/web/frontend/js/features/file-tree/contexts/file-tree-actionable.js
index f631178ff6..14e8f59ba1 100644
--- a/services/web/frontend/js/features/file-tree/contexts/file-tree-actionable.js
+++ b/services/web/frontend/js/features/file-tree/contexts/file-tree-actionable.js
@@ -206,10 +206,10 @@ export function useFileTreeActionable() {
}
function finishCreatingEntity(entity) {
- const selectedEntityId = Array.from(selectedEntityIds)[0]
- const found = findInTreeOrThrow(fileTreeData, selectedEntityId)
- const parentFolderId =
- found.type === 'folder' ? found.entity._id : found.parentFolderId
+ const parentFolderId = getSelectedParentFolderId(
+ fileTreeData,
+ selectedEntityIds
+ )
// check for duplicates and throw
if (isNameUniqueInFolder(fileTreeData, parentFolderId, entity.name)) {
@@ -233,10 +233,10 @@ export function useFileTreeActionable() {
// bypass React file tree entirely; requesting the Angular new doc or file
// modal instead
function startCreatingDocOrFile() {
- const selectedEntityId = Array.from(selectedEntityIds)[0]
- const found = findInTreeOrThrow(fileTreeData, selectedEntityId)
- const parentFolderId =
- found.type === 'folder' ? found.entity._id : found.parentFolderId
+ const parentFolderId = getSelectedParentFolderId(
+ fileTreeData,
+ selectedEntityIds
+ )
window.dispatchEvent(
new CustomEvent('FileTreeReactBridge.openNewDocModal', {
detail: {
@@ -305,7 +305,7 @@ export function useFileTreeActionable() {
return {
canDelete: selectedEntityIds.size > 0,
canRename: selectedEntityIds.size === 1,
- canCreate: selectedEntityIds.size === 1,
+ canCreate: selectedEntityIds.size < 2,
isDeleting,
isRenaming,
isCreatingFolder,
@@ -326,3 +326,15 @@ export function useFileTreeActionable() {
cancel
}
}
+
+function getSelectedParentFolderId(fileTreeData, selectedEntityIds) {
+ // we expect only one entity to be selected in that case, so we pick the first
+ const selectedEntityId = Array.from(selectedEntityIds)[0]
+ if (!selectedEntityId) {
+ // in some cases no entities are selected. Return the root folder id then.
+ return fileTreeData._id
+ }
+
+ const found = findInTreeOrThrow(fileTreeData, selectedEntityId)
+ return found.type === 'folder' ? found.entity._id : found.parentFolderId
+}
diff --git a/services/web/test/frontend/features/file-tree/components/file-tree-toolbar.test.js b/services/web/test/frontend/features/file-tree/components/file-tree-toolbar.test.js
index a28bb69ce1..1869e8af1c 100644
--- a/services/web/test/frontend/features/file-tree/components/file-tree-toolbar.test.js
+++ b/services/web/test/frontend/features/file-tree/components/file-tree-toolbar.test.js
@@ -9,9 +9,9 @@ describe('', function() {
it('without selected files', function() {
renderWithContext()
- expect(screen.queryByRole('button', { name: 'New File' })).to.not.exist
- expect(screen.queryByRole('button', { name: 'New Folder' })).to.not.exist
- expect(screen.queryByRole('button', { name: 'Upload' })).to.not.exist
+ screen.getByRole('button', { name: 'New File' })
+ screen.getByRole('button', { name: 'New Folder' })
+ screen.getByRole('button', { name: 'Upload' })
expect(screen.queryByRole('button', { name: 'Rename' })).to.not.exist
expect(screen.queryByRole('button', { name: 'Delete' })).to.not.exist
})
@@ -29,6 +29,9 @@ describe('', function() {
contextProps: { initialSelectedEntityId: '123abc' }
})
+ screen.getByRole('button', { name: 'New File' })
+ screen.getByRole('button', { name: 'New Folder' })
+ screen.getByRole('button', { name: 'Upload' })
screen.getByRole('button', { name: 'Rename' })
screen.getByRole('button', { name: 'Delete' })
})
diff --git a/services/web/test/frontend/features/file-tree/flows/create-folder.test.js b/services/web/test/frontend/features/file-tree/flows/create-folder.test.js
index dce089a3df..1a78fbb5e1 100644
--- a/services/web/test/frontend/features/file-tree/flows/create-folder.test.js
+++ b/services/web/test/frontend/features/file-tree/flows/create-folder.test.js
@@ -26,7 +26,7 @@ describe('FileTree Create Folder Flow', function() {
delete window._ide
})
- it('add to root', async function() {
+ it('add to root when no files are selected', async function() {
const rootFolder = [
{
_id: 'root-folder-id',
@@ -40,7 +40,6 @@ describe('FileTree Create Folder Flow', function() {
rootFolder={rootFolder}
projectId="123abc"
hasWritePermissions
- rootDocId="456def"
onSelect={onSelect}
onInit={onInit}
/>