diff --git a/src/css/import-resource-tree.css b/src/css/import-resource-tree.css index 020e39a79..715be3139 100644 --- a/src/css/import-resource-tree.css +++ b/src/css/import-resource-tree.css @@ -97,12 +97,18 @@ margin-right: .5rem; } -.import-resource-tree .import-resources-actions .import-resource-status-dropdown .import-resource-status-checkbox { - pointer-events: none; +.import-resource-tree .import-resources-actions .import-resource-status-dropdown { + padding-left: 5px; + gap: 5px; + margin-right: 10px; +} + +.import-resource-tree .import-resources-actions .import-resource-status-dropdown #importSelectCheckboxInput { + cursor: pointer; } .import-resource-tree .import-resources-actions .import-resource-status-dropdown .dropdown-toggle { - padding-left: 0.5rem; + margin-right: 0; } .import-resource-tree .import-resources-actions .import-resource-status-dropdown .dropdown-toggle:not(.selected) { diff --git a/src/js/angular/import/directives/import-resource-tree.directive.js b/src/js/angular/import/directives/import-resource-tree.directive.js index f93196c3c..331c9f7f0 100644 --- a/src/js/angular/import/directives/import-resource-tree.directive.js +++ b/src/js/angular/import/directives/import-resource-tree.directive.js @@ -5,6 +5,7 @@ import {SortingType} from "../../models/import/sorting-type"; import {ImportResourceTreeElement} from "../../models/import/import-resource-tree-element"; import {TABS} from "../services/import-context.service"; import {ImportResourceTreeService} from "../services/import-resource-tree.service"; +import {ResourceListUtil} from "../../models/import/resource-list-wrapper"; import {convertToBytes} from "../../utils/size-util"; const TYPE_FILTER_OPTIONS = { @@ -64,13 +65,12 @@ function importResourceTreeDirective($timeout, ImportContextService) { // ========================= $scope.resources = new ImportResourceTreeElement(); $scope.displayResources = []; + $scope.resourceListUtil = undefined; $scope.TYPE_FILTER_OPTIONS = TYPE_FILTER_OPTIONS; $scope.filterByType = TYPE_FILTER_OPTIONS.ALL; $scope.filterByFileName = ''; $scope.STATUS_OPTIONS = STATUS_OPTIONS; - $scope.selectedByStatus = undefined; - $scope.areAllDisplayedImportResourcesSelected = false; - $scope.areAllDisplayedImportResourcesPartialSelected = false; + $scope.selectedByStatus = STATUS_OPTIONS.NONE; $scope.ImportResourceStatus = ImportResourceStatus; $scope.canRemoveResource = angular.isDefined(attrs.onRemove); $scope.canResetSelectedResources = false; @@ -104,7 +104,13 @@ function importResourceTreeDirective($timeout, ImportContextService) { } else if (STATUS_OPTIONS.IMPORTED === $scope.selectedByStatus) { $scope.resources.selectAllWithStatus([ImportResourceStatus.DONE]); } else if (STATUS_OPTIONS.NOT_IMPORTED === $scope.selectedByStatus) { - $scope.resources.selectAllWithStatus([ImportResourceStatus.IMPORTING, ImportResourceStatus.NONE, ImportResourceStatus.ERROR, ImportResourceStatus.PENDING, ImportResourceStatus.INTERRUPTING]); + $scope.resources.selectAllWithStatus([ + ImportResourceStatus.IMPORTING, + ImportResourceStatus.NONE, + ImportResourceStatus.ERROR, + ImportResourceStatus.PENDING, + ImportResourceStatus.INTERRUPTING + ]); } updateListedImportResources(); @@ -113,11 +119,13 @@ function importResourceTreeDirective($timeout, ImportContextService) { $scope.filterByTypeChanged = (newType) => { $scope.filterByType = newType; + $scope.resourceListUtil.setFilterByType(newType); updateListedImportResources(); }; $scope.filterByFileNameChanged = (filterByFileName) => { $scope.filterByFileName = filterByFileName; + $scope.resourceListUtil.setFilterByName(filterByFileName); debounce(updateListedImportResources, 100); }; @@ -180,6 +188,14 @@ function importResourceTreeDirective($timeout, ImportContextService) { $scope.onEditResource({resource}); }; + $scope.toggleSelectAll = () => { + $scope.resources.setSelection(!($scope.resourceListUtil.areAllDisplayedImportResourcesPartialSelected || + $scope.resourceListUtil.areAllDisplayedImportResourcesSelected)); + + updateListedImportResources(); + setCanResetResourcesFlag(); + }; + // ========================= // Private functions // ========================= @@ -195,10 +211,9 @@ function importResourceTreeDirective($timeout, ImportContextService) { const updateListedImportResources = () => { $scope.resources.getRoot().updateSelectionState(); sortResources(); - $scope.displayResources = $scope.resources.toList() - .filter(filterByType) - .filter(filterByName); - + // Update utility class with sorted resources + $scope.resourceListUtil.setResourceList($scope.resources); + $scope.displayResources = $scope.resourceListUtil.getFilteredResources(); updateHasSelection(); updateSelectByStateDropdownModel(); }; @@ -210,31 +225,32 @@ function importResourceTreeDirective($timeout, ImportContextService) { }; const updateSelectByStateDropdownModel = () => { - const hasUnselectedDisplayedImportResource = $scope.displayResources.some((resource) => !resource.selected); - const hasSelectedDisplayedImportResource = $scope.displayResources.some((resource) => resource.selected); - $scope.areAllDisplayedImportResourcesSelected = hasSelectedDisplayedImportResource && !hasUnselectedDisplayedImportResource; - $scope.areAllDisplayedImportResourcesPartialSelected = hasSelectedDisplayedImportResource && hasUnselectedDisplayedImportResource; + const mainCheckbox = element[0].querySelector('#importSelectCheckboxInput'); + + if (mainCheckbox) { + mainCheckbox.checked = $scope.resourceListUtil.areAllDisplayedResourcesSelectedOrPartial(); + } }; const sortResources = () => { if (SortingType.NAME === $scope.sortedBy) { - $scope.resources.sort(compareByName($scope.sortAsc)); + $scope.resources.sort(nameComparator($scope.sortAsc)); } else if (SortingType.SIZE === $scope.sortedBy) { - $scope.resources.sort(compareBySize($scope.sortAsc)); + $scope.resources.sort(sizeComparator($scope.sortAsc)); } else if (SortingType.MODIFIED === $scope.sortedBy) { - $scope.resources.sort(compareByModified($scope.sortAsc)); + $scope.resources.sort(modifiedByComparator($scope.sortAsc)); } else if (SortingType.IMPORTED === $scope.sortedBy) { - $scope.resources.sort(compareByImportedOn($scope.sortAsc)); + $scope.resources.sort(importedOnComparator($scope.sortAsc)); } else if (SortingType.CONTEXT === $scope.sortedBy) { - $scope.resources.sort(compareByContext($scope.sortAsc)); + $scope.resources.sort(contextComparator($scope.sortAsc)); } }; - const compareByName = (acs) => (r1, r2) => { + const nameComparator = (acs) => (r1, r2) => { return acs ? r1.importResource.name.localeCompare(r2.importResource.name) : r2.importResource.name.localeCompare(r1.importResource.name); }; - const compareBySize = (acs) => (r1, r2) => { + const sizeComparator = (acs) => (r1, r2) => { // The format of size returned by the backend has changed, but we need to keep the old format for backward compatibility. // Therefore, we convert the size to always be in bytes. const r1Size = convertToBytes(r1.importResource.size); @@ -242,53 +258,22 @@ function importResourceTreeDirective($timeout, ImportContextService) { return acs ? r1Size - r2Size : r2Size - r1Size; }; - const compareByModified = (acs) => (r1, r2) => { + const modifiedByComparator = (acs) => (r1, r2) => { const r1ModifiedOn = r1.importResource.modifiedOn || Number.MAX_VALUE; const r2ModifiedOn = r2.importResource.modifiedOn || Number.MAX_VALUE; return acs ? r1ModifiedOn - r2ModifiedOn : r2ModifiedOn - r1ModifiedOn; }; - const compareByImportedOn = (acs) => (r1, r2) => { + const importedOnComparator = (acs) => (r1, r2) => { const r1ImportedOn = r1.importResource.importedOn || Number.MAX_VALUE; const r2ImportedOn = r2.importResource.importedOn || Number.MAX_VALUE; return acs ? r1ImportedOn - r2ImportedOn : r2ImportedOn - r1ImportedOn; }; - const compareByContext = (acs) => (r1, r2) => { + const contextComparator = (acs) => (r1, r2) => { return acs ? r1.importResource.context.localeCompare(r2.importResource.context) : r2.importResource.context.localeCompare(r1.importResource.context); }; - const filterByType = (resource) => { - if (TYPE_FILTER_OPTIONS.ALL === $scope.filterByType) { - return true; - } - - if ($scope.filterByType === TYPE_FILTER_OPTIONS.FILE) { - return resource.isFile(); - } - - if ($scope.filterByType === TYPE_FILTER_OPTIONS.DIRECTORY) { - return resource.isDirectory(); - } - - return false; - }; - - const filterByName = (resource) => { - if (!$scope.filterByFileName) { - return true; - } - - if ($scope.filterByType === TYPE_FILTER_OPTIONS.DIRECTORY) { - return resource.hasTextInDirectoriesName($scope.filterByFileName); - } - - if ($scope.filterByType === TYPE_FILTER_OPTIONS.FILE) { - return resource.hasTextInFilesName($scope.filterByFileName); - } - return resource.hasTextInResourcesName($scope.filterByFileName); - }; - let debounceTimeout; const debounce = (func, delay) => { // Clear previous timeout @@ -314,6 +299,7 @@ function importResourceTreeDirective($timeout, ImportContextService) { } else { ImportResourceTreeService.mergeResourceTree($scope.resources, newResources, isUserImport); } + $scope.resourceListUtil = new ResourceListUtil($scope.resources, $scope.filterByType, $scope.filterByFileName); ImportResourceTreeService.calculateElementIndent($scope.resources); ImportResourceTreeService.setupAfterTreeInitProperties($scope.resources); updateListedImportResources(); diff --git a/src/js/angular/import/templates/import-resource-tree.html b/src/js/angular/import/templates/import-resource-tree.html index 305c09faa..0fc3ff93d 100644 --- a/src/js/angular/import/templates/import-resource-tree.html +++ b/src/js/angular/import/templates/import-resource-tree.html @@ -2,13 +2,12 @@