diff --git a/CHANGELOG.md b/CHANGELOG.md index 44f22257f..82784f37e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [3.3.2] - 2023-11-09: workspace search fails on frontera portal +- WP-380: Remove id prefix filter on workspace search (#898) + +## [3.3.1] - 2023-11-07: Search related bug fixes and App Icon fix +- WP-355: Fixing issue with icons on dev/prod sites (#892) +- WP-354: Workspace search - filter results visible to user (#893) +- WP-356: Site Search: For files, use home dir to isolate the search (#897) +- WP-361: Jobs Search - restrict search to a specific portal (#896) ## [3.3.0] - 2023-10-27: V3 integration improvements; bug fixes @@ -983,7 +991,9 @@ WP-306: Fix target path regression (#871) ## [1.0.0] - 2020-02-28 v1.0.0 Production release as of Feb 28, 2020. -[unreleased]: https://github.com/TACC/Core-Portal/compare/v3.3.0...HEAD +[unreleased]: https://github.com/TACC/Core-Portal/compare/v3.3.2...HEAD +[3.3.2]: https://github.com/TACC/Core-Portal/releases/tag/v3.3.2 +[3.3.1]: https://github.com/TACC/Core-Portal/releases/tag/v3.3.1 [3.3.0]: https://github.com/TACC/Core-Portal/releases/tag/v3.3.0 [3.2.1]: https://github.com/TACC/Core-Portal/releases/tag/v3.2.1 [3.2.0]: https://github.com/TACC/Core-Portal/releases/tag/v3.2.0 diff --git a/client/src/components/Allocations/AllocationsModals/AllocationsTeamViewModal/AllocationsTeamViewModal.jsx b/client/src/components/Allocations/AllocationsModals/AllocationsTeamViewModal/AllocationsTeamViewModal.jsx index 08132979f..413147cb2 100644 --- a/client/src/components/Allocations/AllocationsModals/AllocationsTeamViewModal/AllocationsTeamViewModal.jsx +++ b/client/src/components/Allocations/AllocationsModals/AllocationsTeamViewModal/AllocationsTeamViewModal.jsx @@ -83,6 +83,15 @@ const AllocationsTeamViewModal = ({ isOpen, toggle }) => { const handleTabChange = (e, newValue) => { setSelectedTab(newValue); }; + + let selectedUser = null; + if (removingUserOperation && removingUserOperation.username) { + selectedUser = removingUserOperation.username; + } + if (card && card.username === selectedUser) { + setCard(null); + } + return ( diff --git a/client/src/components/DataFiles/DataFilesProjectsList/DataFilesProjectsList.jsx b/client/src/components/DataFiles/DataFilesProjectsList/DataFilesProjectsList.jsx index 93c4f3181..f90f80791 100644 --- a/client/src/components/DataFiles/DataFilesProjectsList/DataFilesProjectsList.jsx +++ b/client/src/components/DataFiles/DataFilesProjectsList/DataFilesProjectsList.jsx @@ -85,7 +85,9 @@ const DataFilesProjectsList = ({ modal }) => { Header: 'ID', headerStyle: { textAlign: 'left' }, accessor: 'name', - Cell: (el) => {el.value.split('-').slice(-1)[0]}, + Cell: (el) => ( + {el.value ? el.value.split('-').slice(-1)[0] : ''} + ), }, ]; diff --git a/server/portal/apps/projects/views.py b/server/portal/apps/projects/views.py index 5fa35be9a..c61e3bbd3 100644 --- a/server/portal/apps/projects/views.py +++ b/server/portal/apps/projects/views.py @@ -86,8 +86,14 @@ def get(self, request): search = search.extra(from_=int(offset), size=int(limit)) res = search.execute() - hits = [hit.to_dict() for hit in res] - listing = hits + hits = [hit.id for hit in res if hasattr(hit, 'id') and hit.id is not None] + listing = [] + # Filter search results to projects specific to user + if hits: + client = request.user.tapis_oauth.client + listing = list_projects(client) + filtered_list = filter(lambda prj: prj['id'] in hits, listing) + listing = list(filtered_list) else: client = request.user.tapis_oauth.client listing = list_projects(client) diff --git a/server/portal/apps/projects/workspace_operations/shared_workspace_operations.py b/server/portal/apps/projects/workspace_operations/shared_workspace_operations.py index a72cff46e..081a6059a 100644 --- a/server/portal/apps/projects/workspace_operations/shared_workspace_operations.py +++ b/server/portal/apps/projects/workspace_operations/shared_workspace_operations.py @@ -274,9 +274,12 @@ def list_projects(client): fields = "id,host,description,notes,updated,owner,rootDir" query = f"id.like.{settings.PORTAL_PROJECTS_SYSTEM_PREFIX}.*" + # use limit as -1 to allow search to corelate with + # all projects available to the api user listing = client.systems.getSystems(listType='ALL', search=query, - select=fields) + select=fields, + limit=-1) serialized_listing = map(lambda prj: { "id": prj.id, diff --git a/server/portal/apps/site_search/api/unit_test.py b/server/portal/apps/site_search/api/unit_test.py index b871a3e70..3c3911428 100644 --- a/server/portal/apps/site_search/api/unit_test.py +++ b/server/portal/apps/site_search/api/unit_test.py @@ -144,7 +144,7 @@ def test_file_search_util(mock_file_search, regular_user): [{'name': 'testfile', 'path': '/path/to/testfile'}]} client = regular_user.tapis_oauth.client - res = files_search(client, 'test_query', 'test_system') + res = files_search(client, 'test_query', 'test_system', '/',) mock_file_search.assert_called_with(client, 'test_system', '/', query_string='test_query', diff --git a/server/portal/apps/site_search/api/views.py b/server/portal/apps/site_search/api/views.py index 7203e15e2..70cf3cefa 100644 --- a/server/portal/apps/site_search/api/views.py +++ b/server/portal/apps/site_search/api/views.py @@ -36,8 +36,8 @@ def cms_search(query_string, offset=0, limit=10): return total, results -def files_search(client, query_string, system, filter=None, offset=0, limit=10): - res = search_operation(client, system, '/', offset=offset, limit=limit, +def files_search(client, query_string, system, path, filter=None, offset=0, limit=10): + res = search_operation(client, system, path, offset=offset, limit=limit, query_string=query_string, filter=filter) return (res['count'], res['listing']) @@ -65,7 +65,7 @@ def get(self, request, *args, **kwargs): and ('siteSearchPriority' in conf and conf['siteSearchPriority'] is not None)) client = request.user.tapis_oauth.client if (request.user.is_authenticated and request.user.profile.setup_complete) else service_account() (public_total, public_results) = \ - files_search(client, qs, public_conf['system'], filter=filter, + files_search(client, qs, public_conf['system'], public_conf.get("homeDir", "/"), filter=filter, offset=offset, limit=limit) response['public'] = {'count': public_total, 'listing': public_results, @@ -84,7 +84,7 @@ def get(self, request, *args, **kwargs): and ('siteSearchPriority' in conf and conf['siteSearchPriority'] is not None)) client = request.user.tapis_oauth.client (community_total, community_results) = \ - files_search(client, qs, community_conf['system'], filter=filter, + files_search(client, qs, community_conf['system'], community_conf.get("homeDir", "/"), filter=filter, offset=offset, limit=limit) response['community'] = {'count': community_total, diff --git a/server/portal/apps/workspace/api/views.py b/server/portal/apps/workspace/api/views.py index f76b36402..9e263e08a 100644 --- a/server/portal/apps/workspace/api/views.py +++ b/server/portal/apps/workspace/api/views.py @@ -188,7 +188,12 @@ def listing(self, client, request): return data def search(self, client, request): - + ''' + Search using tapis in specific portal with providing query string. + Additonal parameters for search: + limit - limit param from request, otherwise default to 10 + offset - offset param from request, otherwise default to 0 + ''' query_string = request.GET.get('query_string') limit = int(request.GET.get('limit', 10)) @@ -197,10 +202,10 @@ def search(self, client, request): sql_queries = [ f"(tags IN ('portalName: {portal_name}')) AND", - f"(name like '%{query_string}%') OR", + f"((name like '%{query_string}%') OR", f"(archiveSystemDir like '%{query_string}%') OR", f"(appId like '%{query_string}%') OR", - f"(archiveSystemId like '%{query_string}%')", + f"(archiveSystemId like '%{query_string}%'))", ] data = client.jobs.getJobSearchListByPostSqlStr( @@ -212,7 +217,6 @@ def search(self, client, request): }, select="allAttributes" ) - return data def delete(self, request, *args, **kwargs):