imporove sorting management and reduce repetitive code (#381)

* rework sorting management

* remove fdescribe

* test fixes

* unified desctructor

* unified page reload

* test fixes

* code fixes

* test fixes

* test fixes
This commit is contained in:
Denys Vuika 2018-06-02 16:35:55 +01:00 committed by Cilibiu Bogdan
parent 0ac33f820b
commit 7bb0905045
23 changed files with 195 additions and 486 deletions

View File

@ -69,6 +69,7 @@ import { MatMenuModule, MatIconModule, MatButtonModule, MatDialogModule, MatInpu
import { SearchComponent } from './components/search/search.component';
import { SettingsComponent } from './components/settings/settings.component';
import { HybridAppConfigService } from './common/services/hybrid-app-config.service';
import { SortingPreferenceKeyDirective } from './directives/sorting-preference-key.directive';
@NgModule({
imports: [
@ -118,7 +119,8 @@ import { HybridAppConfigService } from './common/services/hybrid-app-config.serv
NodeVersionsDirective,
VersionManagerDialogAdapterComponent,
SearchComponent,
SettingsComponent
SettingsComponent,
SortingPreferenceKeyDirective
],
providers: [
{ provide: AppConfigService, useClass: HybridAppConfigService },

View File

@ -69,7 +69,7 @@ export const APP_ROUTES: Routes = [
{
path: 'favorites',
data: {
preferencePrefix: 'favorites'
sortingPreferenceKey: 'favorites'
},
children: [
{
@ -93,7 +93,7 @@ export const APP_ROUTES: Routes = [
{
path: 'libraries',
data: {
preferencePrefix: 'libraries'
sortingPreferenceKey: 'libraries'
},
children: [{
path: '',
@ -106,7 +106,7 @@ export const APP_ROUTES: Routes = [
component: FilesComponent,
data: {
title: 'APP.BROWSE.LIBRARIES.TITLE',
preferencePrefix: 'libraries-files'
sortingPreferenceKey: 'libraries-files'
}
},
{
@ -123,7 +123,7 @@ export const APP_ROUTES: Routes = [
{
path: 'personal-files',
data: {
preferencePrefix: 'personal-files'
sortingPreferenceKey: 'personal-files'
},
children: [
{
@ -164,7 +164,7 @@ export const APP_ROUTES: Routes = [
{
path: 'recent-files',
data: {
preferencePrefix: 'recent-files'
sortingPreferenceKey: 'recent-files'
},
children: [
{
@ -188,7 +188,7 @@ export const APP_ROUTES: Routes = [
{
path: 'shared',
data: {
preferencePrefix: 'shared-files'
sortingPreferenceKey: 'shared-files'
},
children: [
{
@ -214,7 +214,7 @@ export const APP_ROUTES: Routes = [
component: TrashcanComponent,
data: {
title: 'APP.BROWSE.TRASHCAN.TITLE',
preferencePrefix: 'trashcan'
sortingPreferenceKey: 'trashcan'
}
},
{

View File

@ -54,7 +54,7 @@
<button
mat-menu-item
#selection="adfFavorite"
(toggle)="refresh()"
(toggle)="reload()"
[adf-node-favorite]="documentList.selection">
<mat-icon color="primary" *ngIf="selection.hasFavorites()">star</mat-icon>
<mat-icon *ngIf="!selection.hasFavorites()">star_border</mat-icon>
@ -98,8 +98,8 @@
currentFolderId="-favorites-"
selectionMode="multiple"
[navigate]="false"
[sorting]="sorting"
(sorting-changed)="onSortingChanged($event)"
[sorting]="[ 'modifiedAt', 'desc' ]"
[acaSortingPreferenceKey]="sortingPreferenceKey"
(node-dblclick)="onNodeDoubleClick($event.detail?.node?.entry)">
<empty-folder-content>

View File

@ -25,10 +25,10 @@
import { Observable } from 'rxjs/Rx';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { HttpClientModule } from '@angular/common/http';
import { TestBed, async } from '@angular/core/testing';
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import {
NotificationService, TranslationService, TranslationMock,
NodesApiService, AlfrescoApiService, ContentService,
@ -50,13 +50,12 @@ import { NodePermissionService } from '../../common/services/node-permission.ser
import { FavoritesComponent } from './favorites.component';
describe('Favorites Routed Component', () => {
let fixture;
let fixture: ComponentFixture<FavoritesComponent>;
let component: FavoritesComponent;
let nodesApi: NodesApiService;
let alfrescoApi: AlfrescoApiService;
let alfrescoContentService: ContentService;
let contentService: ContentManagementService;
let preferenceService: UserPreferencesService;
let notificationService: NotificationService;
let router: Router;
let page;
@ -109,9 +108,6 @@ describe('Favorites Routed Component', () => {
AppConfigPipe
],
providers: [
{ provide: ActivatedRoute, useValue: {
snapshot: { data: { preferencePrefix: 'prefix' } }
} } ,
{ provide: TranslationService, useClass: TranslationMock },
AuthenticationService,
UserPreferencesService,
@ -139,7 +135,6 @@ describe('Favorites Routed Component', () => {
alfrescoApi.reset();
alfrescoContentService = TestBed.get(ContentService);
contentService = TestBed.get(ContentManagementService);
preferenceService = TestBed.get(UserPreferencesService);
router = TestBed.get(Router);
});
}));
@ -150,32 +145,32 @@ describe('Favorites Routed Component', () => {
describe('Events', () => {
beforeEach(() => {
spyOn(component, 'refresh');
spyOn(component, 'reload');
fixture.detectChanges();
});
it('should refresh on editing folder event', () => {
alfrescoContentService.folderEdit.next(null);
expect(component.refresh).toHaveBeenCalled();
expect(component.reload).toHaveBeenCalled();
});
it('should refresh on move node event', () => {
contentService.nodeMoved.next(null);
expect(component.refresh).toHaveBeenCalled();
expect(component.reload).toHaveBeenCalled();
});
it('should refresh on node deleted event', () => {
contentService.nodeDeleted.next(null);
expect(component.refresh).toHaveBeenCalled();
expect(component.reload).toHaveBeenCalled();
});
it('should refresh on node restore event', () => {
contentService.nodeRestored.next(null);
expect(component.refresh).toHaveBeenCalled();
expect(component.reload).toHaveBeenCalled();
});
});
@ -292,43 +287,12 @@ describe('Favorites Routed Component', () => {
spyOn(component.documentList, 'reload');
fixture.detectChanges();
component.refresh();
component.reload();
expect(component.documentList.reload).toHaveBeenCalled();
});
});
describe('onSortingChanged', () => {
it('should save sorting input', () => {
spyOn(preferenceService, 'set');
const event = <any>{
detail: {
key: 'some-name',
direction: 'some-direction'
}
};
component.onSortingChanged(event);
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.key', 'some-name');
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.direction', 'some-direction');
});
it('should save default sorting when no input', () => {
spyOn(preferenceService, 'set');
const event = <any>{
detail: {}
};
component.onSortingChanged(event);
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.key', 'modifiedAt');
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.direction', 'desc');
});
});
describe('openSnackMessage', () => {
it('should call notification service', () => {
const message = 'notification message';

View File

@ -23,13 +23,10 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Rx';
import { MinimalNodeEntryEntity, MinimalNodeEntity, PathElementEntity, PathInfo } from 'alfresco-js-api';
import { ContentService, NodesApiService, UserPreferencesService, NotificationService } from '@alfresco/adf-core';
import { DocumentListComponent } from '@alfresco/adf-content-services';
import { ContentManagementService } from '../../common/services/content-management.service';
import { NodePermissionService } from '../../common/services/node-permission.service';
@ -38,44 +35,28 @@ import { PageComponent } from '../page.component';
@Component({
templateUrl: './favorites.component.html'
})
export class FavoritesComponent extends PageComponent implements OnInit, OnDestroy {
@ViewChild(DocumentListComponent)
documentList: DocumentListComponent;
private subscriptions: Subscription[] = [];
sorting = [ 'modifiedAt', 'desc' ];
export class FavoritesComponent extends PageComponent implements OnInit {
constructor(private router: Router,
private route: ActivatedRoute,
route: ActivatedRoute,
private nodesApi: NodesApiService,
private contentService: ContentService,
private content: ContentManagementService,
private notificationService: NotificationService,
public permission: NodePermissionService,
preferences: UserPreferencesService) {
super(preferences);
const sortingKey = preferences.get(`${this.prefix}.sorting.key`) || 'modifiedAt';
const sortingDirection = preferences.get(`${this.prefix}.sorting.direction`) || 'desc';
this.sorting = [sortingKey, sortingDirection];
super(preferences, route);
}
ngOnInit() {
this.subscriptions = this.subscriptions.concat([
this.content.nodeDeleted.subscribe(() => this.refresh()),
this.content.nodeRestored.subscribe(() => this.refresh()),
this.contentService.folderEdit.subscribe(() => this.refresh()),
this.content.nodeMoved.subscribe(() => this.refresh())
this.content.nodeDeleted.subscribe(() => this.reload()),
this.content.nodeRestored.subscribe(() => this.reload()),
this.contentService.folderEdit.subscribe(() => this.reload()),
this.content.nodeMoved.subscribe(() => this.reload())
]);
}
ngOnDestroy() {
this.subscriptions.forEach(s => s.unsubscribe());
}
navigate(favorite: MinimalNodeEntryEntity) {
const { isFolder, id } = favorite;
@ -110,25 +91,10 @@ export class FavoritesComponent extends PageComponent implements OnInit, OnDestr
return selection && selection.length === 1 && selection[0].entry.isFolder;
}
refresh(): void {
if (this.documentList) {
this.documentList.reload();
}
}
onSortingChanged(event: CustomEvent) {
this.preferences.set(`${this.prefix}.sorting.key`, event.detail.key || 'modifiedAt');
this.preferences.set(`${this.prefix}.sorting.direction`, event.detail.direction || 'desc');
}
openSnackMessage(event: any) {
this.notificationService.openSnackMessage(
event,
4000
);
}
private get prefix() {
return this.route.snapshot.data.preferencePrefix;
}
}

View File

@ -109,14 +109,13 @@
[disabled]="!permission.check(node, ['create'])">
<adf-document-list #documentList
[sorting]="[ 'modifiedAt', 'desc' ]"
[acaSortingPreferenceKey]="sortingPreferenceKey"
selectionMode="multiple"
[currentFolderId]="node?.id"
[sorting]="sorting"
[allowDropFiles]="true"
[navigate]="false"
[imageResolver]="imageResolver"
(sorting-changed)="onSortingChanged($event)"
(node-dblclick)="onNodeDoubleClick($event)"
(node-select)="onNodeSelect($event, documentList)">

View File

@ -62,7 +62,6 @@ describe('FilesComponent', () => {
let router: Router;
let browsingFilesService: BrowsingFilesService;
let nodeActionsService: NodeActionsService;
let preferenceService: UserPreferencesService;
let notificationService: NotificationService;
beforeEach(async(() => {
@ -89,8 +88,8 @@ describe('FilesComponent', () => {
],
providers: [
{ provide: ActivatedRoute, useValue: {
params: Observable.of({ folderId: 'someId' }),
snapshot: { data: { preferencePrefix: 'prefix' } }
snapshot: { data: { preferencePrefix: 'prefix' } },
params: Observable.of({ folderId: 'someId' })
} } ,
{ provide: TranslationService, useClass: TranslationMock },
AuthenticationService,
@ -125,7 +124,6 @@ describe('FilesComponent', () => {
browsingFilesService = TestBed.get(BrowsingFilesService);
notificationService = TestBed.get(NotificationService);
nodeActionsService = TestBed.get(NodeActionsService);
preferenceService = TestBed.get(UserPreferencesService);
});
}));
@ -454,37 +452,6 @@ describe('FilesComponent', () => {
});
});
describe('onSortingChanged', () => {
it('should save sorting input', () => {
spyOn(preferenceService, 'set');
const event = <any>{
detail: {
key: 'some-name',
direction: 'some-direction'
}
};
component.onSortingChanged(event);
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.key', 'some-name');
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.direction', 'some-direction');
});
it('should save default sorting when no input', () => {
spyOn(preferenceService, 'set');
const event = <any>{
detail: {}
};
component.onSortingChanged(event);
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.key', 'modifiedAt');
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.direction', 'desc');
});
});
describe('openSnackMessage', () => {
it('should call notification service', () => {
const message = 'notification message';

View File

@ -23,8 +23,8 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { Observable, Subscription } from 'rxjs/Rx';
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { MinimalNodeEntity, MinimalNodeEntryEntity, PathElementEntity, NodePaging, PathElement } from 'alfresco-js-api';
import {
@ -32,8 +32,6 @@ import {
ContentService, AlfrescoApiService, UserPreferencesService, NotificationService
} from '@alfresco/adf-core';
import { DocumentListComponent } from '@alfresco/adf-content-services';
import { BrowsingFilesService } from '../../common/services/browsing-files.service';
import { ContentManagementService } from '../../common/services/content-management.service';
import { NodeActionsService } from '../../common/services/node-actions.service';
@ -45,17 +43,13 @@ import { PageComponent } from '../page.component';
templateUrl: './files.component.html'
})
export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
@ViewChild(DocumentListComponent) documentList: DocumentListComponent;
isValidPath = true;
private nodePath: PathElement[];
private subscriptions: Subscription[] = [];
sorting = [ 'modifiedAt', 'desc' ];
constructor(private router: Router,
private route: ActivatedRoute,
route: ActivatedRoute,
private nodesApi: NodesApiService,
private nodeActionsService: NodeActionsService,
private uploadService: UploadService,
@ -66,12 +60,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
private notificationService: NotificationService,
public permission: NodePermissionService,
preferences: UserPreferencesService) {
super(preferences);
const sortingKey = this.preferences.get(`${this.prefix}.sorting.key`) || 'modifiedAt';
const sortingDirection = this.preferences.get(`${this.prefix}.sorting.direction`) || 'desc';
this.sorting = [sortingKey, sortingDirection];
super(preferences, route);
}
ngOnInit() {
@ -116,8 +105,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
}
ngOnDestroy() {
this.subscriptions.forEach(s => s.unsubscribe());
super.ngOnDestroy();
this.browsingFilesService.onChangeParent.next(null);
}
@ -269,19 +257,10 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
return false;
}
onSortingChanged(event: CustomEvent) {
this.preferences.set(`${this.prefix}.sorting.key`, event.detail.key || 'modifiedAt');
this.preferences.set(`${this.prefix}.sorting.direction`, event.detail.direction || 'desc');
}
openSnackMessage(event: any) {
this.notificationService.openSnackMessage(
event,
4000
);
}
private get prefix() {
return this.route.snapshot.data.preferencePrefix;
}
}

View File

@ -12,8 +12,8 @@
currentFolderId="-mysites-"
selectionMode="none"
[navigate]="false"
[sorting]="sorting"
(sorting-changed)="onSortingChanged($event)"
[sorting]="[ 'title', 'asc' ]"
[acaSortingPreferenceKey]="sortingPreferenceKey"
(node-dblclick)="onNodeDoubleClick($event)">
<empty-folder-content>

View File

@ -23,10 +23,10 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { TestBed, async } from '@angular/core/testing';
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { Observable } from 'rxjs/Rx';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { HttpClientModule } from '@angular/common/http';
import {
@ -46,12 +46,11 @@ import { ShareDataTableAdapter } from '@alfresco/adf-content-services';
import { LibrariesComponent } from './libraries.component';
describe('Libraries Routed Component', () => {
let fixture;
let fixture: ComponentFixture<LibrariesComponent>;
let component: LibrariesComponent;
let nodesApi: NodesApiService;
let alfrescoApi: AlfrescoApiService;
let router: Router;
let preferenceService: UserPreferencesService;
let page;
let node;
@ -91,9 +90,6 @@ describe('Libraries Routed Component', () => {
AppConfigPipe
],
providers: [
{ provide: ActivatedRoute, useValue: {
snapshot: { data: { preferencePrefix: 'prefix' } }
} } ,
{ provide: TranslationService, useClass: TranslationMock },
AuthenticationService,
UserPreferencesService,
@ -117,7 +113,6 @@ describe('Libraries Routed Component', () => {
alfrescoApi = TestBed.get(AlfrescoApiService);
alfrescoApi.reset();
router = TestBed.get(Router);
preferenceService = TestBed.get(UserPreferencesService);
});
}));
@ -230,35 +225,4 @@ describe('Libraries Routed Component', () => {
expect(component.navigate).not.toHaveBeenCalled();
});
});
describe('onSortingChanged', () => {
it('should save sorting input', () => {
spyOn(preferenceService, 'set');
const event = <any>{
detail: {
key: 'some-name',
direction: 'some-direction'
}
};
component.onSortingChanged(event);
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.key', 'some-name');
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.direction', 'some-direction');
});
it('should save default sorting when no input', () => {
spyOn(preferenceService, 'set');
const event = <any>{
detail: {}
};
component.onSortingChanged(event);
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.key', 'modifiedAt');
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.direction', 'desc');
});
});
});

View File

@ -23,10 +23,10 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component, ViewChild } from '@angular/core';
import { Component } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { NodesApiService, UserPreferencesService } from '@alfresco/adf-core';
import { DocumentListComponent, ShareDataRow } from '@alfresco/adf-content-services';
import { ShareDataRow } from '@alfresco/adf-content-services';
import { PageComponent } from '../page.component';
@ -35,21 +35,11 @@ import { PageComponent } from '../page.component';
})
export class LibrariesComponent extends PageComponent {
@ViewChild(DocumentListComponent)
documentList: DocumentListComponent;
sorting = [ 'title', 'asc' ];
constructor(private nodesApi: NodesApiService,
private route: ActivatedRoute,
route: ActivatedRoute,
private router: Router,
preferences: UserPreferencesService) {
super(preferences);
const sortingKey = preferences.get(`${this.prefix}.sorting.key`) || 'title';
const sortingDirection = preferences.get(`${this.prefix}.sorting.direction`) || 'desc';
this.sorting = [sortingKey, sortingDirection];
super(preferences, route);
}
makeLibraryTooltip(library: any): string {
@ -92,13 +82,4 @@ export class LibrariesComponent extends PageComponent {
});
}
}
onSortingChanged(event: CustomEvent) {
this.preferences.set(`${this.prefix}.sorting.key`, event.detail.key || 'modifiedAt');
this.preferences.set(`${this.prefix}.sorting.direction`, event.detail.direction || 'desc');
}
private get prefix() {
return this.route.snapshot.data.preferencePrefix;
}
}

View File

@ -29,7 +29,7 @@ class TestClass extends PageComponent {
node: any;
constructor() {
super(null);
super(null, null);
}
}

View File

@ -25,18 +25,36 @@
import { MinimalNodeEntity, MinimalNodeEntryEntity, Pagination } from 'alfresco-js-api';
import { UserPreferencesService } from '@alfresco/adf-core';
import { ShareDataRow } from '@alfresco/adf-content-services';
import { ShareDataRow, DocumentListComponent } from '@alfresco/adf-content-services';
import { ActivatedRoute } from '@angular/router';
import { OnDestroy, ViewChild } from '@angular/core';
import { Subscription } from 'rxjs/Rx';
export abstract class PageComponent implements OnDestroy {
@ViewChild(DocumentListComponent)
documentList: DocumentListComponent;
export abstract class PageComponent {
title = 'Page';
infoDrawerOpened = false;
node: MinimalNodeEntryEntity;
protected subscriptions: Subscription[] = [];
get sortingPreferenceKey(): string {
return this.route.snapshot.data.sortingPreferenceKey;
}
static isLockedNode(node) {
return node.isLocked || (node.properties && node.properties['cm:lockType'] === 'READ_ONLY_LOCK');
}
constructor(protected preferences: UserPreferencesService) {
constructor(protected preferences: UserPreferencesService, protected route: ActivatedRoute) {
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => subscription.unsubscribe());
this.subscriptions = [];
}
getParentNodeId(): string {
@ -121,4 +139,11 @@ export abstract class PageComponent {
this.infoDrawerOpened = !this.infoDrawerOpened;
}
reload(): void {
if (this.documentList) {
this.documentList.resetSelection();
this.documentList.reload();
}
}
}

View File

@ -91,9 +91,9 @@
currentFolderId="-recent-"
selectionMode="multiple"
[navigate]="false"
[sorting]="sorting"
[sorting]="[ 'modifiedAt', 'desc' ]"
[acaSortingPreferenceKey]="sortingPreferenceKey"
[imageResolver]="imageResolver"
(sorting-changed)="onSortingChanged($event)"
(node-dblclick)="onNodeDoubleClick($event.detail?.node?.entry)"
(node-select)="onNodeSelect($event, documentList)">

View File

@ -23,9 +23,9 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { TestBed, async } from '@angular/core/testing';
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { HttpClientModule } from '@angular/common/http';
import {
@ -47,12 +47,11 @@ import { NodePermissionService } from '../../common/services/node-permission.ser
import { RecentFilesComponent } from './recent-files.component';
describe('RecentFiles Routed Component', () => {
let fixture;
let component;
let fixture: ComponentFixture<RecentFilesComponent>;
let component: RecentFilesComponent;
let router: Router;
let alfrescoApi: AlfrescoApiService;
let contentService: ContentManagementService;
let preferenceService: UserPreferencesService;
let page;
beforeEach(() => {
@ -85,9 +84,6 @@ describe('RecentFiles Routed Component', () => {
AppConfigPipe
],
providers: [
{ provide: ActivatedRoute, useValue: {
snapshot: { data: { preferencePrefix: 'prefix' } }
} } ,
{ provide: TranslationService, useClass: TranslationMock },
AuthenticationService,
UserPreferencesService,
@ -111,7 +107,6 @@ describe('RecentFiles Routed Component', () => {
router = TestBed.get(Router);
contentService = TestBed.get(ContentManagementService);
preferenceService = TestBed.get(UserPreferencesService);
alfrescoApi = TestBed.get(AlfrescoApiService);
alfrescoApi.reset();
});
@ -127,7 +122,7 @@ describe('RecentFiles Routed Component', () => {
describe('OnInit()', () => {
beforeEach(() => {
spyOn(component, 'refresh').and.stub();
spyOn(component, 'reload').and.stub();
});
it('should reload nodes on onDeleteNode event', () => {
@ -135,7 +130,7 @@ describe('RecentFiles Routed Component', () => {
contentService.nodeDeleted.next();
expect(component.refresh).toHaveBeenCalled();
expect(component.reload).toHaveBeenCalled();
});
it('should reload on onRestoreNode event', () => {
@ -143,7 +138,7 @@ describe('RecentFiles Routed Component', () => {
contentService.nodeRestored.next();
expect(component.refresh).toHaveBeenCalled();
expect(component.reload).toHaveBeenCalled();
});
it('should reload on move node event', () => {
@ -151,7 +146,7 @@ describe('RecentFiles Routed Component', () => {
contentService.nodeMoved.next();
expect(component.refresh).toHaveBeenCalled();
expect(component.reload).toHaveBeenCalled();
});
});
@ -182,40 +177,9 @@ describe('RecentFiles Routed Component', () => {
spyOn(component.documentList, 'reload');
fixture.detectChanges();
component.refresh();
component.reload();
expect(component.documentList.reload).toHaveBeenCalled();
});
});
describe('onSortingChanged', () => {
it('should save sorting input', () => {
spyOn(preferenceService, 'set');
const event = <any>{
detail: {
key: 'some-name',
direction: 'some-direction'
}
};
component.onSortingChanged(event);
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.key', 'some-name');
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.direction', 'some-direction');
});
it('should save default sorting when no input', () => {
spyOn(preferenceService, 'set');
const event = <any>{
detail: {}
};
component.onSortingChanged(event);
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.key', 'modifiedAt');
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.direction', 'desc');
});
});
});

View File

@ -23,12 +23,10 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { Subscription } from 'rxjs/Rx';
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { MinimalNodeEntryEntity } from 'alfresco-js-api';
import { UserPreferencesService } from '@alfresco/adf-core';
import { DocumentListComponent } from '@alfresco/adf-content-services';
import { ContentManagementService } from '../../common/services/content-management.service';
import { PageComponent } from '../page.component';
@ -37,41 +35,25 @@ import { NodePermissionService } from '../../common/services/node-permission.ser
@Component({
templateUrl: './recent-files.component.html'
})
export class RecentFilesComponent extends PageComponent implements OnInit, OnDestroy {
@ViewChild(DocumentListComponent)
documentList: DocumentListComponent;
private subscriptions: Subscription[] = [];
sorting = [ 'modifiedAt', 'desc' ];
export class RecentFilesComponent extends PageComponent implements OnInit {
constructor(
private router: Router,
private route: ActivatedRoute,
route: ActivatedRoute,
private content: ContentManagementService,
public permission: NodePermissionService,
preferences: UserPreferencesService) {
super(preferences);
const sortingKey = preferences.get(`${this.prefix}.sorting.key`) || 'modifiedAt';
const sortingDirection = preferences.get(`${this.prefix}.sorting.direction`) || 'desc';
this.sorting = [sortingKey, sortingDirection];
super(preferences, route);
}
ngOnInit() {
this.subscriptions = this.subscriptions.concat([
this.content.nodeDeleted.subscribe(() => this.refresh()),
this.content.nodeMoved.subscribe(() => this.refresh()),
this.content.nodeRestored.subscribe(() => this.refresh())
this.content.nodeDeleted.subscribe(() => this.reload()),
this.content.nodeMoved.subscribe(() => this.reload()),
this.content.nodeRestored.subscribe(() => this.reload())
]);
}
ngOnDestroy() {
this.subscriptions.forEach(s => s.unsubscribe());
}
onNodeDoubleClick(node: MinimalNodeEntryEntity) {
if (node && PageComponent.isLockedNode(node)) {
event.preventDefault();
@ -80,19 +62,4 @@ export class RecentFilesComponent extends PageComponent implements OnInit, OnDes
this.router.navigate(['./preview', node.id], { relativeTo: this.route });
}
}
refresh(): void {
if (this.documentList) {
this.documentList.reload();
}
}
onSortingChanged(event: CustomEvent) {
this.preferences.set(`${this.prefix}.sorting.key`, event.detail.key || 'modifiedAt');
this.preferences.set(`${this.prefix}.sorting.direction`, event.detail.direction || 'desc');
}
private get prefix() {
return this.route.snapshot.data.preferencePrefix;
}
}

View File

@ -98,8 +98,8 @@
<adf-document-list #documentList
currentFolderId="-sharedlinks-"
selectionMode="multiple"
[sorting]="sorting"
(sorting-changed)="onSortingChanged($event)"
[sorting]="[ 'modifiedAt', 'desc' ]"
[acaSortingPreferenceKey]="sortingPreferenceKey"
(node-dblclick)="onNodeDoubleClick($event.detail?.node?.entry)">
<empty-folder-content>

View File

@ -23,9 +23,9 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { TestBed, async, fakeAsync, tick } from '@angular/core/testing';
import { TestBed, async, fakeAsync, tick, ComponentFixture } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { HttpClientModule } from '@angular/common/http';
import {
@ -47,12 +47,11 @@ import { NodePermissionService } from '../../common/services/node-permission.ser
import { SharedFilesComponent } from './shared-files.component';
describe('SharedFilesComponent', () => {
let fixture;
let fixture: ComponentFixture<SharedFilesComponent>;
let component: SharedFilesComponent;
let contentService: ContentManagementService;
let nodeService;
let alfrescoApi: AlfrescoApiService;
let preferenceService: UserPreferencesService;
let router: Router;
let page;
@ -87,9 +86,6 @@ describe('SharedFilesComponent', () => {
AppConfigPipe
],
providers: [
{ provide: ActivatedRoute, useValue: {
snapshot: { data: { preferencePrefix: 'prefix' } }
} } ,
{ provide: TranslationService, useClass: TranslationMock },
AuthenticationService,
UserPreferencesService,
@ -116,7 +112,6 @@ describe('SharedFilesComponent', () => {
alfrescoApi = TestBed.get(AlfrescoApiService);
alfrescoApi.reset();
nodeService = alfrescoApi.getInstance().nodes;
preferenceService = TestBed.get(UserPreferencesService);
router = TestBed.get(Router);
});
@ -128,7 +123,7 @@ describe('SharedFilesComponent', () => {
describe('OnInit', () => {
beforeEach(() => {
spyOn(component, 'refresh').and.callFake(val => val);
spyOn(component, 'reload').and.callFake(val => val);
});
it('should refresh on deleteNode event', () => {
@ -136,7 +131,7 @@ describe('SharedFilesComponent', () => {
contentService.nodeDeleted.next();
expect(component.refresh).toHaveBeenCalled();
expect(component.reload).toHaveBeenCalled();
});
it('should refresh on restoreNode event', () => {
@ -144,7 +139,7 @@ describe('SharedFilesComponent', () => {
contentService.nodeRestored.next();
expect(component.refresh).toHaveBeenCalled();
expect(component.reload).toHaveBeenCalled();
});
it('should reload on move node event', () => {
@ -152,7 +147,7 @@ describe('SharedFilesComponent', () => {
contentService.nodeMoved.next();
expect(component.refresh).toHaveBeenCalled();
expect(component.reload).toHaveBeenCalled();
});
});
@ -199,40 +194,9 @@ describe('SharedFilesComponent', () => {
spyOn(component.documentList, 'reload');
fixture.detectChanges();
component.refresh();
component.reload();
expect(component.documentList.reload).toHaveBeenCalled();
});
});
describe('onSortingChanged', () => {
it('should save sorting input', () => {
spyOn(preferenceService, 'set');
const event = <any>{
detail: {
key: 'some-name',
direction: 'some-direction'
}
};
component.onSortingChanged(event);
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.key', 'some-name');
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.direction', 'some-direction');
});
it('should save default sorting when no input', () => {
spyOn(preferenceService, 'set');
const event = <any>{
detail: {}
};
component.onSortingChanged(event);
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.key', 'modifiedAt');
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.direction', 'desc');
});
});
});

View File

@ -23,12 +23,10 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component, OnInit, ViewChild, OnDestroy } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Rx';
import { MinimalNodeEntity } from 'alfresco-js-api';
import { AlfrescoApiService, UserPreferencesService } from '@alfresco/adf-core';
import { DocumentListComponent } from '@alfresco/adf-content-services';
import { ContentManagementService } from '../../common/services/content-management.service';
import { NodePermissionService } from '../../common/services/node-permission.service';
@ -37,41 +35,25 @@ import { PageComponent } from '../page.component';
@Component({
templateUrl: './shared-files.component.html'
})
export class SharedFilesComponent extends PageComponent implements OnInit, OnDestroy {
@ViewChild(DocumentListComponent)
documentList: DocumentListComponent;
private subscriptions: Subscription[] = [];
sorting = [ 'modifiedAt', 'desc' ];
export class SharedFilesComponent extends PageComponent implements OnInit {
constructor(private router: Router,
private route: ActivatedRoute,
route: ActivatedRoute,
private content: ContentManagementService,
private apiService: AlfrescoApiService,
public permission: NodePermissionService,
preferences: UserPreferencesService) {
super(preferences);
const sortingKey = preferences.get(`${this.prefix}.sorting.key`) || 'modifiedAt';
const sortingDirection = preferences.get(`${this.prefix}.sorting.direction`) || 'desc';
this.sorting = [sortingKey, sortingDirection];
super(preferences, route);
}
ngOnInit() {
this.subscriptions = this.subscriptions.concat([
this.content.nodeDeleted.subscribe(() => this.refresh()),
this.content.nodeMoved.subscribe(() => this.refresh()),
this.content.nodeRestored.subscribe(() => this.refresh())
this.content.nodeDeleted.subscribe(() => this.reload()),
this.content.nodeMoved.subscribe(() => this.reload()),
this.content.nodeRestored.subscribe(() => this.reload())
]);
}
ngOnDestroy() {
this.subscriptions.forEach(s => s.unsubscribe());
}
onNodeDoubleClick(link: { nodeId?: string }) {
if (link && link.nodeId) {
this.apiService.nodesApi.getNode(link.nodeId).then(
@ -88,20 +70,4 @@ export class SharedFilesComponent extends PageComponent implements OnInit, OnDes
isFileSelected(selection: Array<MinimalNodeEntity>): boolean {
return selection && selection.length === 1;
}
refresh(): void {
if (this.documentList) {
this.documentList.resetSelection();
this.documentList.reload();
}
}
onSortingChanged(event: CustomEvent) {
this.preferences.set(`${this.prefix}.sorting.key`, event.detail.key || 'modifiedAt');
this.preferences.set(`${this.prefix}.sorting.direction`, event.detail.direction || 'desc');
}
private get prefix() {
return this.route.snapshot.data.preferencePrefix;
}
}

View File

@ -32,8 +32,8 @@
currentFolderId="-trashcan-"
selectionMode="multiple"
[navigate]="false"
[sorting]="sorting"
(sorting-changed)="onSortingChanged($event)">
[sorting]="[ 'archivedAt', 'desc' ]"
[acaSortingPreferenceKey]="sortingPreferenceKey">
<empty-folder-content>
<ng-template>

View File

@ -23,10 +23,9 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { HttpClientModule } from '@angular/common/http';
import { TestBed, async } from '@angular/core/testing';
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import {
NotificationService, TranslationService, TranslationMock,
NodesApiService, AlfrescoApiService, ContentService,
@ -46,11 +45,10 @@ import { NodeInfoDirective } from '../../common/directives/node-info.directive';
import { TrashcanComponent } from './trashcan.component';
describe('TrashcanComponent', () => {
let fixture;
let component;
let fixture: ComponentFixture<TrashcanComponent>;
let component: TrashcanComponent;
let alfrescoApi: AlfrescoApiService;
let contentService: ContentManagementService;
let preferenceService: UserPreferencesService;
let page;
beforeEach(() => {
@ -83,9 +81,6 @@ describe('TrashcanComponent', () => {
AppConfigPipe
],
providers: [
{ provide: ActivatedRoute, useValue: {
snapshot: { data: { preferencePrefix: 'prefix' } }
} } ,
{ provide: TranslationService, useClass: TranslationMock },
AuthenticationService,
UserPreferencesService,
@ -110,9 +105,8 @@ describe('TrashcanComponent', () => {
alfrescoApi = TestBed.get(AlfrescoApiService);
alfrescoApi.reset();
contentService = TestBed.get(ContentManagementService);
preferenceService = TestBed.get(UserPreferencesService);
component.documentList = {
component.documentList = <any> {
reload: jasmine.createSpy('reload'),
resetSelection: jasmine.createSpy('resetSelection')
};
@ -125,55 +119,24 @@ describe('TrashcanComponent', () => {
describe('onRestoreNode()', () => {
it('should call refresh()', () => {
spyOn(component, 'refresh');
spyOn(component, 'reload');
fixture.detectChanges();
contentService.nodeRestored.next();
expect(component.refresh).toHaveBeenCalled();
expect(component.reload).toHaveBeenCalled();
});
});
describe('refresh()', () => {
it('calls child component to reload', () => {
component.refresh();
component.reload();
expect(component.documentList.reload).toHaveBeenCalled();
});
it('calls child component to reset selection', () => {
component.refresh();
component.reload();
expect(component.documentList.resetSelection).toHaveBeenCalled();
});
});
describe('onSortingChanged', () => {
it('should save sorting input', () => {
spyOn(preferenceService, 'set');
const event = <any>{
detail: {
key: 'some-name',
direction: 'some-direction'
}
};
component.onSortingChanged(event);
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.key', 'some-name');
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.direction', 'some-direction');
});
it('should save default sorting when no input', () => {
spyOn(preferenceService, 'set');
const event = <any>{
detail: {}
};
component.onSortingChanged(event);
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.key', 'archivedAt');
expect(preferenceService.set).toHaveBeenCalledWith('prefix.sorting.direction', 'desc');
});
});
});

View File

@ -23,57 +23,31 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Rx';
import { Pagination } from 'alfresco-js-api';
import { UserPreferencesService } from '@alfresco/adf-core';
import { DocumentListComponent } from '@alfresco/adf-content-services';
import { ContentManagementService } from '../../common/services/content-management.service';
import { PageComponent } from '../page.component';
@Component({
templateUrl: './trashcan.component.html'
})
export class TrashcanComponent implements OnInit, OnDestroy {
private subscriptions: Subscription[] = [];
@ViewChild(DocumentListComponent) documentList;
sorting = [ 'archivedAt', 'desc' ];
export class TrashcanComponent extends PageComponent implements OnInit {
constructor(private contentManagementService: ContentManagementService,
private preferences: UserPreferencesService,
private route: ActivatedRoute) {
const sortingKey = preferences.get(`${this.prefix}.sorting.key`) || 'archivedAt';
const sortingDirection = preferences.get(`${this.prefix}.sorting.direction`) || 'desc';
this.sorting = [sortingKey, sortingDirection];
preferences: UserPreferencesService,
route: ActivatedRoute) {
super(preferences, route);
}
ngOnInit() {
this.subscriptions.push(this.contentManagementService.nodeRestored.subscribe(() => this.refresh()));
}
refresh(): void {
this.documentList.reload();
this.documentList.resetSelection();
}
ngOnDestroy() {
this.subscriptions.forEach(s => s.unsubscribe());
this.subscriptions.push(
this.contentManagementService.nodeRestored.subscribe(() => this.reload())
);
}
onChangePageSize(event: Pagination): void {
this.preferences.paginationSize = event.maxItems;
}
onSortingChanged(event: CustomEvent) {
this.preferences.set(`${this.prefix}.sorting.key`, event.detail.key || 'archivedAt');
this.preferences.set(`${this.prefix}.sorting.direction`, event.detail.direction || 'desc');
}
private get prefix() {
return this.route.snapshot.data.preferencePrefix;
}
}

View File

@ -0,0 +1,64 @@
/*!
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
*
* This file is part of the Alfresco Example Content Application.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { Directive, Input, OnInit, HostListener } from '@angular/core';
import { DocumentListComponent } from '@alfresco/adf-content-services';
import { UserPreferencesService } from '@alfresco/adf-core';
@Directive({
selector: '[acaSortingPreferenceKey]',
})
export class SortingPreferenceKeyDirective implements OnInit {
// tslint:disable-next-line:no-input-rename
@Input('acaSortingPreferenceKey')
preferenceKey: string;
constructor(
private documentList: DocumentListComponent,
private userPreferencesService: UserPreferencesService) {
}
@HostListener('sorting-changed', ['$event'])
onSortingChanged(event: CustomEvent) {
if (this.preferenceKey) {
this.userPreferencesService.set(`${this.preferenceKey}.sorting.key`, event.detail.key);
this.userPreferencesService.set(`${this.preferenceKey}.sorting.direction`, event.detail.direction);
}
}
ngOnInit() {
if (this.preferenceKey) {
const current = this.documentList.sorting;
const key = this.userPreferencesService.get(`${this.preferenceKey}.sorting.key`, current[0]);
const direction = this.userPreferencesService.get(`${this.preferenceKey}.sorting.direction`, current[1]);
this.documentList.sorting = [key, direction];
// TODO: bug in ADF, the `sorting` binding is not updated when changed from code
this.documentList.data.setSorting({ key, direction });
}
}
}