From 741062553183455a2e80963678f3666343faf133 Mon Sep 17 00:00:00 2001 From: Jake Rosenberg Date: Wed, 31 Jan 2024 17:15:24 -0600 Subject: [PATCH] bug/DES-2695: Community data shows the wrong files being selected (#1165) * fix bug where community data showed the wrong files being selected * fix test --- .../data-depot-browser.component.js | 5 +- .../files-listing.template.html | 2 +- .../services/file-listing-service.js | 66 ++++++++++--------- .../services/file-listing-service.spec.js | 2 +- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/designsafe/static/scripts/data-depot/components/data-depot-browser/data-depot-browser.component.js b/designsafe/static/scripts/data-depot/components/data-depot-browser/data-depot-browser.component.js index a69fbe2dd6..436dbd4a35 100644 --- a/designsafe/static/scripts/data-depot/components/data-depot-browser/data-depot-browser.component.js +++ b/designsafe/static/scripts/data-depot/components/data-depot-browser/data-depot-browser.component.js @@ -60,11 +60,14 @@ class DataDepotBrowserCtrl { this.scheme = this.FileListingService.fileMgrMappings[this.apiParams.fileMgr].scheme; const system = this.$stateParams.systemId || 'external'; const path = this.$stateParams.filePath + if (system === 'designsafe.storage.community') { + this.exclude = ['.Trash'] + } this.offset = 0; this.limit = 15; const queryString = this.$stateParams.query_string; - this.FileListingService.browse({section: this.section, api: this.api, scheme: this.scheme, system, path, query_string: queryString}); + this.FileListingService.browse({section: this.section, api: this.api, scheme: this.scheme, system, path, query_string: queryString, exclude: this.exclude}); } onBrowse(file) { diff --git a/designsafe/static/scripts/data-depot/components/data-depot-listing/files-listing.template.html b/designsafe/static/scripts/data-depot/components/data-depot-listing/files-listing.template.html index c70d04ef40..00b570ba04 100644 --- a/designsafe/static/scripts/data-depot/components/data-depot-listing/files-listing.template.html +++ b/designsafe/static/scripts/data-depot/components/data-depot-listing/files-listing.template.html @@ -26,7 +26,7 @@ diff --git a/designsafe/static/scripts/ng-designsafe/services/file-listing-service.js b/designsafe/static/scripts/ng-designsafe/services/file-listing-service.js index b1e255e66a..1e638f3a9f 100644 --- a/designsafe/static/scripts/ng-designsafe/services/file-listing-service.js +++ b/designsafe/static/scripts/ng-designsafe/services/file-listing-service.js @@ -4,16 +4,7 @@ import { takeLeadingSubscriber, takeLatestSubscriber } from './_rxjs-utils'; import { uuid } from 'uuidv4'; export class FileListingService { - constructor( - $http, - $uibModal, - $rootScope, - $q, - $timeout, - ProjectService, - FileOperationService, - Django - ) { + constructor($http, $uibModal, $rootScope, $q, $timeout, ProjectService, FileOperationService, Django) { 'ngInject'; this.count = 0; this.$rootScope = $rootScope; @@ -286,8 +277,19 @@ export class FileListingService { * @param {number} params.limit Number of results to return. * @param {string} params.query_string Optional query string for search. */ - browse({ section, api, scheme, system, path, offset, limit, query_string, doi }) { - const params = { section, api, scheme, system, path, offset: offset || 0, limit: limit || 100, query_string, doi }; + browse({ section, api, scheme, system, path, offset, limit, query_string, doi, exclude }) { + const params = { + section, + api, + scheme, + system, + path, + offset: offset || 0, + limit: limit || 100, + query_string, + doi, + exclude, + }; this.updateParams(section, params); // Deselect any selected files and update permissions on operations. if (section === 'main') { @@ -319,7 +321,7 @@ export class FileListingService { * @param {number} params.limit Number of results to return. * @param {string} params.query_string Optional query string for search. */ - mapParamsToListing({ section, api, scheme, system, path, offset, limit, query_string }) { + mapParamsToListing({ section, api, scheme, system, path, offset, limit, query_string, exclude }) { const operation = query_string ? 'search' : 'listing'; const listingUrl = this.removeDuplicateSlashes( `/api/datafiles/${api}/${scheme}/${operation}/${system}/${path}/` @@ -329,7 +331,7 @@ export class FileListingService { params: { offset, limit, query_string }, }); const listingObservable$ = this.from(request).pipe( - tap(this.listingSuccessCallback(section)), + tap(this.listingSuccessCallback(section, exclude)), catchError(this.listingErrorCallback(section)) ); return listingObservable$; @@ -340,10 +342,12 @@ export class FileListingService { * to each file and determines whether it is possible to list more files. * @param {string} section */ - listingSuccessCallback(section) { + listingSuccessCallback(section, exclude) { return (resp) => { this.listings[section].error = null; - this.listings[section].listing = resp.data.listing.map((f) => ({ ...f, key: uuid(), selected: false })); + this.listings[section].listing = resp.data.listing + .map((f) => ({ ...f, key: uuid(), selected: false })) + .filter((f) => exclude ? !exclude.includes(f.name) : true); this.listings[section].loading = false; resp.data.nextPageToken && this.updateParams(section, { nextPageToken: resp.data.nextPageToken }); this.listings[section].reachedEnd = @@ -561,22 +565,22 @@ export class FileListingService { tap(this.abstractListingSuccessCallback(entitiesPerPath)), catchError(() => { // If the listing fails, construct a synthetic listing as placeholder. - const children = Object.keys(entitiesPerPath).filter(k => k.startsWith(path)) - const syntheticListing = children.map(path => { + const children = Object.keys(entitiesPerPath).filter((k) => k.startsWith(path)); + const syntheticListing = children.map((path) => { // Assume path is a dir if it doesn't contain a '.' character. - const type = path.search((/\./)) > 0 ? 'file' : 'dir' + const type = path.search(/\./) > 0 ? 'file' : 'dir'; return { name: path.split('/').slice(-1)[0], path, system, permissions: 'ALL', type, - format: type === 'dir' ? 'folder' : 'raw' - } - }) - const synthResponse = {data: {listing: syntheticListing}} - this.abstractListingSuccessCallback(entitiesPerPath)(synthResponse) - return of(null) + format: type === 'dir' ? 'folder' : 'raw', + }; + }); + const synthResponse = { data: { listing: syntheticListing } }; + this.abstractListingSuccessCallback(entitiesPerPath)(synthResponse); + return of(null); }) ); return listingObservable$; @@ -621,9 +625,11 @@ export class FileListingService { this.addSection(entity.uuid); this.listings[entity.uuid].listing = []; this.listings[entity.uuid].params = { section: entity.uuid, ...abstractListingParams }; - entity._filePaths.filter(s => s !== '/').forEach((path) => { - entitiesPerPath[path] = [...(entitiesPerPath[path] || []), entity]; - }); + entity._filePaths + .filter((s) => s !== '/') + .forEach((path) => { + entitiesPerPath[path] = [...(entitiesPerPath[path] || []), entity]; + }); }); // Concatenate all entity._filePath arrays. const allPaths = Object.keys(entitiesPerPath); @@ -683,9 +689,9 @@ export class FileListingService { * @param {Object} entity Entity to perform the abstract listing for. */ publishedListing(publication, entity) { - const basePath = (publication.revision + const basePath = publication.revision ? `${publication.projectId}v${publication.revision}` - : publication.projectId) + : publication.projectId; const publicationListingParams = { api: 'agave', scheme: 'public', diff --git a/designsafe/static/scripts/ng-designsafe/services/file-listing-service.spec.js b/designsafe/static/scripts/ng-designsafe/services/file-listing-service.spec.js index d84617fd5e..c5077b5ab3 100644 --- a/designsafe/static/scripts/ng-designsafe/services/file-listing-service.spec.js +++ b/designsafe/static/scripts/ng-designsafe/services/file-listing-service.spec.js @@ -46,7 +46,7 @@ describe('FileListingService', function() { flush(); // Fires callback after it emits. - expect(FileListingService.listingSuccessCallback).toHaveBeenCalledWith('main'); + expect(FileListingService.listingSuccessCallback).toHaveBeenCalledWith('main', undefined); }; testScheduler.run(observableTests); });