Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NXDRIVE-2942: Improve folder selection on Direct Transfer screen #5189

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changes/5.5.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Release date: `2024-xx-xx`
### Direct Transfer

- [NXDRIVE-2915](https://jira.nuxeo.com/browse/NXDRIVE-2915): Translate "Document type" and "container type" labels on Direct Transfer popup
- [NXDRIVE-2942](https://jira.nuxeo.com/browse/NXDRIVE-2942): Improve folder selection on Direct Transfer screen

### Task Management
- [NXDRIVE-2](https://jira.nuxeo.com/browse/NXDRIVE-2):
Expand Down
2 changes: 2 additions & 0 deletions nxdrive/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
errno.ERANGE, # Result too large
}

QUERY_ENDPOINT = "/api/v1/search/lang/NXQL/execute?query="

# OSError indicating the incapacity to do anything because of too long file name or deep tree
LONG_FILE_ERRORS = {errno.ENAMETOOLONG}
if WINDOWS:
Expand Down
8 changes: 6 additions & 2 deletions nxdrive/gui/folders_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,14 @@
return
elif info.get_id() not in self.tree.cache:
self.tree.cache.append(info.get_id())

try:
if info:
children = list(self.tree.client.get_children(info))
if not info.is_expandable() and not info.get_path().startswith(

Check warning on line 48 in nxdrive/gui/folders_loader.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_loader.py#L48

Added line #L48 was not covered by tests
"/default-domain/UserWorkspaces/"
):
children = []

Check warning on line 51 in nxdrive/gui/folders_loader.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_loader.py#L51

Added line #L51 was not covered by tests
else:
children = list(self.tree.client.get_children(info))

Check warning on line 53 in nxdrive/gui/folders_loader.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_loader.py#L53

Added line #L53 was not covered by tests
else:
children = list(self.tree.client.get_top_documents())
except Exception:
Expand Down
85 changes: 71 additions & 14 deletions nxdrive/gui/folders_model.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from logging import getLogger
from typing import Iterator, List, Union
from typing import Any, Iterator, List, Union

from nuxeo.models import Document

Expand Down Expand Up @@ -81,45 +81,72 @@
class Doc(FileInfo):
"""A folderish document. Used by the Direct Transfer feature."""

def __init__(self, doc: Document, /, *, parent: FileInfo = None) -> None:
def __init__(
self, doc: Document, expandable: bool = True, /, *, parent: FileInfo = None
) -> None:
super().__init__(parent=parent)
self.doc = doc
self.expandable = expandable

Check warning on line 89 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L89

Added line #L89 was not covered by tests

def __repr__(self) -> str:
return (
f"{type(self).__name__}<id={self.get_id()}, label={self.get_label()}, "
f"is_expandable={self.is_expandable()!r}, "
f"parent={self.get_path()!r}, enable={self.enable()!r}, selectable={self.selectable()!r}>"
)

def is_expandable(self) -> bool:
"""Returns if the current user is an Admin"""
return self.expandable

Check warning on line 100 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L100

Added line #L100 was not covered by tests

def folderish(self) -> bool:
"""Only folders are used, so it is always True."""
return True

def enable(self) -> bool:
"""Allow to select the folder only if the user can effectively create documents inside."""
return (
"HiddenInCreation" not in self.doc.facets
and self.doc.type not in Options.disallowed_types_for_dt
and "AddChildren" in self.doc.contextParameters["permissions"]
)
try:
return (

Check warning on line 109 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L108-L109

Added lines #L108 - L109 were not covered by tests
"HiddenInCreation" not in self.doc.facets
and self.doc.type not in Options.disallowed_types_for_dt
and "AddChildren" in self.doc.contextParameters["permissions"]
)
except Exception:
return (

Check warning on line 115 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L114-L115

Added lines #L114 - L115 were not covered by tests
"HiddenInCreation" not in self.doc["facets"]
and self.doc["type"] not in Options.disallowed_types_for_dt
and "AddChildren" in self.doc["contextParameters"]["permissions"]
)

def get_id(self) -> str:
"""The document's UID."""
return self.doc.uid
try:
return self.doc.uid
except Exception:
return self.doc["uid"]

Check warning on line 126 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L123-L126

Added lines #L123 - L126 were not covered by tests

def get_label(self) -> str:
"""The document's name as it is showed in the tree."""
return self.doc.title
try:
return self.doc.title
except Exception:
return self.doc["title"]

Check warning on line 133 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L130-L133

Added lines #L130 - L133 were not covered by tests

def get_path(self) -> str:
"""Guess the document's path on the server."""
return self.doc.path
try:
return self.doc.path
except Exception:
return self.doc["path"]

Check warning on line 140 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L137-L140

Added lines #L137 - L140 were not covered by tests

def selectable(self) -> bool:
"""Allow to fetch its children only if the user has at least the "Read" permission
and if it contains at least one subfolder.
"""
return "Read" in self.doc.contextParameters["permissions"]
try:
return "Read" in self.doc.contextParameters["permissions"]
except Exception:
return "Read" in self.doc["contextParameters"]["permissions"]

Check warning on line 149 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L146-L149

Added lines #L146 - L149 were not covered by tests


class FilteredDoc(FileInfo):
Expand Down Expand Up @@ -147,9 +174,14 @@
def __repr__(self) -> str:
return (
f"{type(self).__name__}<state={self.state}, id={self.get_id()}, "
f"is_expandable={self.is_expandable()!r}, "
f"label={self.get_label()}, folderish={self.folderish()!r}, parent={self.get_path()!r}>"
)

def is_expandable(self) -> bool:
"""Returns if the current user is an Admin"""
return True

Check warning on line 183 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L183

Added line #L183 was not covered by tests

def get_label(self) -> str:
"""The document's name as it is showed in the tree."""
return self.fs_info.name
Expand Down Expand Up @@ -247,6 +279,12 @@
)
)

def get_roots(self) -> List[Any]:
from ..constants import QUERY_ENDPOINT

Check warning on line 283 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L283

Added line #L283 was not covered by tests

url = f"{QUERY_ENDPOINT}select * from Document WHERE ecm:mixinType = 'Folderish' and ecm:isTrashed = 0"
return self.remote.client.request("GET", url).json()["entries"]

Check warning on line 286 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L285-L286

Added lines #L285 - L286 were not covered by tests

def _get_root_folders(self) -> List["Documents"]:
"""Get root folders.
Use a try...except block to prevent loading error on the root,
Expand All @@ -256,9 +294,28 @@
root = self.remote.documents.get(path="/")
return [Doc(doc) for doc in self._get_children(root.uid)]
except Exception:
log.warning("Error while retrieving documents on '/'", exc_info=True)
context = {"permissions": [], "hasFolderishChild": False}
return [Doc(Document(title="/", contextParameters=context))]
if Options.shared_folder_navigation:
roots = self.get_roots()
ret_list = []
for root in roots:
if root["type"] == "Folder" and not root["path"].startswith(

Check warning on line 301 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L297-L301

Added lines #L297 - L301 were not covered by tests
"/default-domain/UserWorkspaces/"
):
doc = self.remote.fetch(

Check warning on line 304 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L304

Added line #L304 was not covered by tests
root["uid"],
enrichers=["permissions"],
)
if (

Check warning on line 308 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L308

Added line #L308 was not covered by tests
"Write" in doc["contextParameters"]["permissions"]
or "ReadWrite" in doc["contextParameters"]["permissions"]
or "Everything" in doc["contextParameters"]["permissions"]
):
ret_list.append(Doc(doc, False))
return ret_list

Check warning on line 314 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L313-L314

Added lines #L313 - L314 were not covered by tests
else:
log.warning("Error while retrieving documents on '/'", exc_info=True)
context = {"permissions": [], "hasFolderishChild": False}
return [Doc(Document(title="/", contextParameters=context))]

Check warning on line 318 in nxdrive/gui/folders_model.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_model.py#L316-L318

Added lines #L316 - L318 were not covered by tests

def get_top_documents(self) -> Iterator["Documents"]:
"""Fetch all documents at the root."""
Expand Down
14 changes: 7 additions & 7 deletions nxdrive/gui/folders_treeview.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,13 @@

def on_selection_changed(self, current: QModelIndex, _: QModelIndex, /) -> None:
"""Actions to do when a folder is selected."""
item = self.model().itemFromIndex(current).data(qt.UserRole)
self.parent.remote_folder.setText(item.get_path())
self.parent.remote_folder_ref = item.get_id()
self.parent.remote_folder_title = item.get_label()
self.current = current
self.parent.button_ok_state()
self.parent.update_file_group()
if item := self.model().itemFromIndex(current).data(qt.UserRole):
self.parent.remote_folder.setText(item.get_path())
self.parent.remote_folder_ref = item.get_id()
self.parent.remote_folder_title = item.get_label()
self.current = current
self.parent.button_ok_state()
self.parent.update_file_group()

Check warning on line 193 in nxdrive/gui/folders_treeview.py

View check run for this annotation

Codecov / codecov/patch

nxdrive/gui/folders_treeview.py#L187-L193

Added lines #L187 - L193 were not covered by tests

def refresh_selected(self) -> None:
"""Force reload the the current selected index."""
Expand Down
1 change: 1 addition & 0 deletions nxdrive/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ class MetaOptions(type):
"debug_pydev": (False, "default"),
"delay": (30, "default"),
"deletion_behavior": ("unsync", "default"),
"shared_folder_navigation": (False, "default"),
"disabled_file_integrity_check": (False, "default"),
"disallowed_types_for_dt": (__doctypes_no_dt, "default"),
"dt_hide_personal_space": (False, "default"),
Expand Down