Skip to content

Commit

Permalink
[ACA-4728] fix file order in viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
g-jaskowski committed Mar 14, 2024
1 parent 8512e42 commit fd92766
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,7 @@ describe('PreviewComponent', () => {
});

it('should fetch and sort file ids for personal-files', async () => {
preferences.set('personal-files.sorting.key', 'name');
preferences.set('personal-files.sorting.direction', 'desc');
spyOn(preferences, 'get').and.returnValues('name', 'desc', 'client');

spyOn(contentApi, 'getNodeChildren').and.returnValue(
of({
Expand All @@ -484,8 +483,7 @@ describe('PreviewComponent', () => {
});

it('should fetch file ids for personal-files with default sorting for missing key', async () => {
preferences.set('personal-files.sorting.key', 'missing');
preferences.set('personal-files.sorting.direction', 'desc');
spyOn(preferences, 'get').and.returnValues('missing', 'desc', 'client');

spyOn(contentApi, 'getNodeChildren').and.returnValue(
of({
Expand All @@ -500,7 +498,7 @@ describe('PreviewComponent', () => {
});

it('should sort file ids for personal-files with [modifiedAt desc]', async () => {
spyOn(preferences, 'get').and.returnValue(null);
spyOn(preferences, 'get').and.returnValues(null, null, 'client');

spyOn(contentApi, 'getNodeChildren').and.returnValue(
of({
Expand Down Expand Up @@ -752,6 +750,24 @@ describe('PreviewComponent', () => {
expect(component.navigateToFileLocation).toHaveBeenCalled();
});

it('should not sort personal files when server-side sorting is set', async () => {
spyOn(preferences, 'get').and.returnValues('name', 'desc', 'server');

spyOn(contentApi, 'getNodeChildren').and.returnValue(
of({
list: {
entries: [
{ entry: { id: 'node1', name: 'node 1', modifiedAt: new Date(1) } },
{ entry: { id: 'node2', name: 'node 2', modifiedAt: new Date(2) } }
]
}
} as NodePaging)
);

const ids = await component.getFileIds('personal-files', 'folder1');
expect(ids).toEqual(['node1', 'node2']);
});

describe('Keyboard navigation', () => {
beforeEach(() => {
component.nextNodeId = 'nextNodeId';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,14 +317,16 @@ export class PreviewComponent extends PageComponent implements OnInit, OnDestroy
const sortDirection = this.preferences.get('personal-files.sorting.direction') || 'desc';
const nodes = await this.contentApi
.getNodeChildren(folderId, {
// orderBy: `${sortKey} ${sortDirection}`,
orderBy: ['isFolder desc', `${sortKey} ${sortDirection}`],
fields: ['id', this.getRootField(sortKey)],
where: '(isFile=true)'
})
.toPromise();

const entries = nodes.list.entries.map((obj) => obj.entry);
this.sort(entries, sortKey, sortDirection);
if (this.preferences.get('filesPageSortingMode') === 'client' || source === 'libraries') {
this.sort(entries, sortKey, sortDirection);
}

return entries.map((obj) => obj.id);
}
Expand Down
30 changes: 25 additions & 5 deletions projects/aca-content/src/lib/components/files/files.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/

import { DataTableModule, PaginationModule, ShowHeaderMode } from '@alfresco/adf-core';
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { DataTableModule, PaginationModule, ShowHeaderMode, UserPreferencesService } from '@alfresco/adf-core';
import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { NodeEntry, Node, PathElement } from '@alfresco/js-api';
import { NodeActionsService } from '../../services/node-actions.service';
Expand All @@ -39,7 +39,15 @@ import {
} from '@alfresco/aca-shared';
import { SetCurrentFolderAction, isAdmin, UploadFileVersionAction, showLoaderSelector } from '@alfresco/aca-shared/store';
import { debounceTime, takeUntil } from 'rxjs/operators';
import { FilterSearch, ShareDataRow, FileUploadEvent, BreadcrumbModule, UploadModule, DocumentListModule } from '@alfresco/adf-content-services';
import {
BreadcrumbModule,
DocumentListComponent,
DocumentListModule,
FilterSearch,
FileUploadEvent,
UploadModule,
ShareDataRow
} from '@alfresco/adf-content-services';
import { DocumentListPresetRef, ExtensionsModule } from '@alfresco/adf-extensions';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
Expand Down Expand Up @@ -69,7 +77,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
templateUrl: './files.component.html',
encapsulation: ViewEncapsulation.None
})
export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
export class FilesComponent extends PageComponent implements OnInit, OnDestroy, AfterViewInit {
isValidPath = true;
isAdmin = false;
selectedNode: NodeEntry;
Expand All @@ -81,7 +89,15 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
columns: DocumentListPresetRef[] = [];
isFilterHeaderActive = false;

constructor(private route: ActivatedRoute, private contentApi: ContentApiService, private nodeActionsService: NodeActionsService) {
@ViewChild('documentList', { static: true })
documentList: DocumentListComponent;

constructor(
private route: ActivatedRoute,
private contentApi: ContentApiService,
private nodeActionsService: NodeActionsService,
private preferences: UserPreferencesService
) {
super();
}

Expand Down Expand Up @@ -136,6 +152,10 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
}
}

ngAfterViewInit() {
this.preferences.set('filesPageSortingMode', this.documentList.sortingMode);
}

ngOnDestroy() {
this.store.dispatch(new SetCurrentFolderAction(null));
super.ngOnDestroy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,41 +22,199 @@
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AcaViewerComponent } from '@alfresco/aca-content/viewer';
import { NodesApiService } from '@alfresco/adf-content-services';
import { RefreshPreviewAction } from '@alfresco/aca-shared/store';
import { Node } from '@alfresco/js-api';
import { EMPTY } from 'rxjs';
import { CoreTestingModule } from '@alfresco/adf-core';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import {
UserPreferencesService,
AlfrescoApiService,
AlfrescoApiServiceMock,
AuthenticationService,
TranslationMock,
TranslationService,
PipeModule
} from '@alfresco/adf-core';
import { DiscoveryApiService, NodesApiService } from '@alfresco/adf-content-services';
import { AppState, RefreshPreviewAction } from '@alfresco/aca-shared/store';
import { AcaViewerComponent } from './viewer.component';
import { BehaviorSubject, Observable, of } from 'rxjs';
import { ContentApiService, DocumentBasePageService } from '@alfresco/aca-shared';
import { Store, StoreModule } from '@ngrx/store';
import { NodePaging, RepositoryInfo, VersionInfo, Node } from '@alfresco/js-api';
import { AcaViewerModule } from '../../viewer.module';
import { TranslateModule } from '@ngx-translate/core';
import { RouterTestingModule } from '@angular/router/testing';
import { HttpClientModule } from '@angular/common/http';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { EffectsModule } from '@ngrx/effects';

describe('AcaViewerComponent', () => {
class DocumentBasePageServiceMock extends DocumentBasePageService {
canUpdateNode(): boolean {
return true;
}
canUploadContent(): boolean {
return true;
}
}

export const INITIAL_APP_STATE: AppState = {
appName: 'Alfresco Content Application',
logoPath: 'assets/images/alfresco-logo-white.svg',
customCssPath: '',
webFontPath: '',
sharedUrl: '',
user: {
isAdmin: null,
id: null,
firstName: '',
lastName: ''
},
selection: {
nodes: [],
libraries: [],
isEmpty: true,
count: 0
},
navigation: {
currentFolder: null
},
currentNodeVersion: null,
infoDrawerOpened: false,
infoDrawerPreview: false,
infoDrawerMetadataAspect: '',
showFacetFilter: true,
fileUploadingDialog: true,
showLoader: false,
repository: {
status: {
isQuickShareEnabled: true
}
} as any
};

describe('ViewerComponent', () => {
let fixture: ComponentFixture<AcaViewerComponent>;
let component: AcaViewerComponent;
let preferences: UserPreferencesService;
let contentApi: ContentApiService;
let nodesApiService: NodesApiService;
let store: Store<any>;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, StoreModule.forRoot({})]
imports: [
AcaViewerModule,
NoopAnimationsModule,
HttpClientModule,
RouterTestingModule,
TranslateModule.forRoot(),
StoreModule.forRoot(
{ app: (state) => state },
{
initialState: {
app: INITIAL_APP_STATE
},
runtimeChecks: {
strictStateImmutability: false,
strictActionImmutability: false
}
}
),
EffectsModule.forRoot([]),
PipeModule
],
providers: [
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
{ provide: TranslationService, useClass: TranslationMock },
{ provide: DocumentBasePageService, useVale: new DocumentBasePageServiceMock() },
{
provide: DiscoveryApiService,
useValue: {
ecmProductInfo$: new BehaviorSubject<RepositoryInfo | null>(null),
getEcmProductInfo: (): Observable<RepositoryInfo> =>
of(
new RepositoryInfo({
version: {
major: '10.0.0'
} as VersionInfo
})
)
}
},
{
provide: AuthenticationService,
useValue: {
isEcmLoggedIn: (): boolean => true,
getRedirect: (): string | null => null,
setRedirect() {},
isOauth: (): boolean => false,
isOAuthWithoutSilentLogin: (): boolean => false
}
}
]
});

store = TestBed.inject(Store);
spyOn(store, 'select').and.returnValue(EMPTY);
fixture = TestBed.createComponent(AcaViewerComponent);
component = fixture.componentInstance;

preferences = TestBed.inject(UserPreferencesService);
contentApi = TestBed.inject(ContentApiService);
nodesApiService = TestBed.inject(NodesApiService);
store = TestBed.inject(Store);
});

describe('Load content', () => {
it('should call node update after RefreshPreviewAction is triggered', () => {
spyOn(nodesApiService.nodeUpdated, 'next');
component.ngOnInit();
const node = new Node();
it('should fetch and sort file ids for personal-files', async () => {
spyOn(preferences, 'get').and.returnValues('name', 'desc', 'client');

store.dispatch(new RefreshPreviewAction(node));
expect(nodesApiService.nodeUpdated.next).toHaveBeenCalledWith(node);
});
spyOn(contentApi, 'getNodeChildren').and.returnValue(
of({
list: {
entries: [{ entry: { id: 'node1', name: 'node 1' } }, { entry: { id: 'node2', name: 'node 2' } }]
}
} as NodePaging)
);

const ids = await component.getFileIds('personal-files', 'folder1');
expect(ids).toEqual(['node2', 'node1']);
});

it('should fetch file ids for personal-files with default sorting for missing key', async () => {
spyOn(preferences, 'get').and.returnValues('missing', 'desc', 'client');

spyOn(contentApi, 'getNodeChildren').and.returnValue(
of({
list: {
entries: [{ entry: { id: 'node1', name: 'node 1' } }, { entry: { id: 'node2', name: 'node 2' } }]
}
} as NodePaging)
);

const ids = await component.getFileIds('personal-files', 'folder1');
expect(ids).toEqual(['node1', 'node2']);
});

it('should not sort personal files when server-side sorting is set', async () => {
spyOn(preferences, 'get').and.returnValues('name', 'desc', 'server');

spyOn(contentApi, 'getNodeChildren').and.returnValue(
of({
list: {
entries: [
{ entry: { id: 'node1', name: 'node 1', modifiedAt: new Date(1) } },
{ entry: { id: 'node2', name: 'node 2', modifiedAt: new Date(2) } }
]
}
} as NodePaging)
);

const ids = await component.getFileIds('personal-files', 'folder1');
expect(ids).toEqual(['node1', 'node2']);
});

it('should call node update after RefreshPreviewAction is triggered', () => {
spyOn(nodesApiService.nodeUpdated, 'next');
component.ngOnInit();
const node = new Node();

store.dispatch(new RefreshPreviewAction(node));
expect(nodesApiService.nodeUpdated.next).toHaveBeenCalledWith(node);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -323,14 +323,15 @@ export class AcaViewerComponent implements OnInit, OnDestroy {
const sortDirection = this.preferences.get('personal-files.sorting.direction') || 'desc';
const nodes = await this.contentApi
.getNodeChildren(folderId, {
// orderBy: `${sortKey} ${sortDirection}`,
orderBy: ['isFolder desc', `${sortKey} ${sortDirection}`],
fields: ['id', this.getRootField(sortKey)],
where: '(isFile=true)'
})
.toPromise();

const entries = nodes.list.entries.map((obj) => obj.entry);
this.sort(entries, sortKey, sortDirection);
if (this.preferences.get('filesPageSortingMode') === 'client' || source === 'libraries') {
this.sort(entries, sortKey, sortDirection);
}

return entries.map((obj) => obj.id);
}
Expand Down

0 comments on commit fd92766

Please sign in to comment.