library effects and actions (#441)

* library effects and actions

* single selection and test fixes

* navigate to site route

* add experimental flag

* disable test

* update tests
This commit is contained in:
Denys Vuika
2018-06-21 19:56:08 +01:00
committed by GitHub
parent 02647c003a
commit 045c4ee9a2
13 changed files with 174 additions and 16 deletions

View File

@@ -99,7 +99,7 @@ describe('Toolbar actions - single selection : ', () => {
.then(done); .then(done);
}); });
it('actions not displayed for top level of File Libraries', () => { xit('actions not displayed for top level of File Libraries', () => {
page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.FILE_LIBRARIES) page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.FILE_LIBRARIES)
.then(() => dataTable.waitForHeader()) .then(() => dataTable.waitForHeader())
.then(() => dataTable.clickOnItemName(userSite)) .then(() => dataTable.clickOnItemName(userSite))

View File

@@ -8,7 +8,9 @@
"copyright": "copyright":
"© 2017 - 2018 Alfresco Software, Inc. All rights reserved." "© 2017 - 2018 Alfresco Software, Inc. All rights reserved."
}, },
"experimental": {}, "experimental": {
"libraries": true
},
"headerColor": "#2196F3", "headerColor": "#2196F3",
"languagePicker": false, "languagePicker": false,
"pagination": { "pagination": {

View File

@@ -29,6 +29,7 @@ import { Observable } from 'rxjs/Rx';
import { AlfrescoApiService } from '@alfresco/adf-core'; import { AlfrescoApiService } from '@alfresco/adf-core';
import { import {
MinimalNodeEntity, MinimalNodeEntity,
MinimalNodeEntryEntity,
PathInfoEntity, PathInfoEntity,
DeletedNodesPaging DeletedNodesPaging
} from 'alfresco-js-api'; } from 'alfresco-js-api';
@@ -230,12 +231,12 @@ export class NodeRestoreDirective {
if (message) { if (message) {
if (status.oneSucceeded && !status.someFailed) { if (status.oneSucceeded && !status.someFailed) {
const isSite = this.isSite(status.success[0].entry);
const path: PathInfoEntity = status.success[0].entry.path; const path: PathInfoEntity = status.success[0].entry.path;
const parent = path.elements[path.elements.length - 1]; const parent = path.elements[path.elements.length - 1];
const navigate = new NavigateRouteAction([ const route = isSite ? ['/libraries'] : ['/personal-files', parent.id];
'/personal-files',
parent.id const navigate = new NavigateRouteAction(route);
]);
message.userAction = new SnackbarUserAction( message.userAction = new SnackbarUserAction(
'APP.ACTIONS.VIEW', 'APP.ACTIONS.VIEW',
@@ -247,6 +248,10 @@ export class NodeRestoreDirective {
} }
} }
private isSite(entry: MinimalNodeEntryEntity): boolean {
return entry.nodeType === 'st:site';
}
private refresh(): void { private refresh(): void {
this.contentManagementService.nodesRestored.next(); this.contentManagementService.nodesRestored.next();
} }

View File

@@ -34,4 +34,5 @@ export class ContentManagementService {
nodesRestored = new Subject<any>(); nodesRestored = new Subject<any>();
folderEdited = new Subject<any>(); folderEdited = new Subject<any>();
folderCreated = new Subject<any>(); folderCreated = new Subject<any>();
siteDeleted = new Subject<string>();
} }

View File

@@ -2,7 +2,24 @@
<div class="inner-layout__header"> <div class="inner-layout__header">
<adf-breadcrumb root="APP.BROWSE.LIBRARIES.TITLE"> <adf-breadcrumb root="APP.BROWSE.LIBRARIES.TITLE">
</adf-breadcrumb> </adf-breadcrumb>
<adf-toolbar class="inline"> <adf-toolbar class="inline" *ngIf="!selection.isEmpty">
<ng-container *ifExperimental="'libraries'">
<button
color="primary"
mat-icon-button
title="{{ 'APP.ACTIONS.MORE' | translate }}"
[matMenuTriggerFor]="actionsMenu">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #actionsMenu="matMenu" [overlapTrigger]="false">
<button
mat-menu-item
(click)="deleteLibrary(selection.first)">
<mat-icon>delete</mat-icon>
<span>{{ 'APP.ACTIONS.DELETE' | translate }}</span>
</button>
</mat-menu>
</ng-container>
</adf-toolbar> </adf-toolbar>
</div> </div>
@@ -10,7 +27,7 @@
<div class="inner-layout__panel"> <div class="inner-layout__panel">
<adf-document-list acaDocumentList #documentList <adf-document-list acaDocumentList #documentList
currentFolderId="-mysites-" currentFolderId="-mysites-"
selectionMode="none" selectionMode="single"
[navigate]="false" [navigate]="false"
[sorting]="[ 'title', 'asc' ]" [sorting]="[ 'title', 'asc' ]"
(node-dblclick)="onNodeDoubleClick($event)"> (node-dblclick)="onNodeDoubleClick($event)">

View File

@@ -47,6 +47,8 @@ import { LibrariesComponent } from './libraries.component';
import { StoreModule } from '@ngrx/store'; import { StoreModule } from '@ngrx/store';
import { appReducer } from '../../store/reducers/app.reducer'; import { appReducer } from '../../store/reducers/app.reducer';
import { INITIAL_STATE } from '../../store/states/app.state'; import { INITIAL_STATE } from '../../store/states/app.state';
import { ContentManagementService } from '../../common/services/content-management.service';
import { ExperimentalDirective } from '../../directives/experimental.directive';
describe('Libraries Routed Component', () => { describe('Libraries Routed Component', () => {
let fixture: ComponentFixture<LibrariesComponent>; let fixture: ComponentFixture<LibrariesComponent>;
@@ -91,7 +93,8 @@ describe('Libraries Routed Component', () => {
NodeFavoriteDirective, NodeFavoriteDirective,
DocumentListComponent, DocumentListComponent,
LibrariesComponent, LibrariesComponent,
AppConfigPipe AppConfigPipe,
ExperimentalDirective
], ],
providers: [ providers: [
{ provide: TranslationService, useClass: TranslationMock }, { provide: TranslationService, useClass: TranslationMock },
@@ -105,7 +108,9 @@ describe('Libraries Routed Component', () => {
NodesApiService, NodesApiService,
DocumentListService, DocumentListService,
ThumbnailService, ThumbnailService,
CustomResourcesService CustomResourcesService,
ContentManagementService
], ],
schemas: [ NO_ERRORS_SCHEMA ] schemas: [ NO_ERRORS_SCHEMA ]
}) })

View File

@@ -23,7 +23,7 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { Component } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router'; import { Router, ActivatedRoute } from '@angular/router';
import { NodesApiService } from '@alfresco/adf-core'; import { NodesApiService } from '@alfresco/adf-core';
import { ShareDataRow } from '@alfresco/adf-content-services'; import { ShareDataRow } from '@alfresco/adf-content-services';
@@ -31,19 +31,31 @@ import { ShareDataRow } from '@alfresco/adf-content-services';
import { PageComponent } from '../page.component'; import { PageComponent } from '../page.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppStore } from '../../store/states/app.state'; import { AppStore } from '../../store/states/app.state';
import { DeleteLibraryAction } from '../../store/actions';
import { SiteEntry } from 'alfresco-js-api';
import { ContentManagementService } from '../../common/services/content-management.service';
@Component({ @Component({
templateUrl: './libraries.component.html' templateUrl: './libraries.component.html'
}) })
export class LibrariesComponent extends PageComponent { export class LibrariesComponent extends PageComponent implements OnInit {
constructor(private nodesApi: NodesApiService, constructor(private nodesApi: NodesApiService,
private route: ActivatedRoute, private route: ActivatedRoute,
private content: ContentManagementService,
store: Store<AppStore>, store: Store<AppStore>,
private router: Router) { private router: Router) {
super(store); super(store);
} }
ngOnInit() {
super.ngOnInit();
this.subscriptions.push(
this.content.siteDeleted.subscribe(() => this.reload())
);
}
makeLibraryTooltip(library: any): string { makeLibraryTooltip(library: any): string {
const { description, title } = library; const { description, title } = library;
@@ -84,4 +96,10 @@ export class LibrariesComponent extends PageComponent {
}); });
} }
} }
deleteLibrary(node: SiteEntry) {
if (node && node.entry) {
this.store.dispatch(new DeleteLibraryAction(node.entry.id));
}
}
} }

View File

@@ -30,3 +30,4 @@ export * from './actions/router.actions';
export * from './actions/viewer.actions'; export * from './actions/viewer.actions';
export * from './actions/search.actions'; export * from './actions/search.actions';
export * from './actions/user.actions'; export * from './actions/user.actions';
export * from './actions/library.actions';

View File

@@ -0,0 +1,33 @@
/*!
* @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 { Action } from '@ngrx/store';
export const DELETE_LIBRARY = 'DELETE_LIBRARY';
export class DeleteLibraryAction implements Action {
readonly type = DELETE_LIBRARY;
constructor(public payload: string) {}
}

View File

@@ -37,7 +37,8 @@ import {
RouterEffects, RouterEffects,
DownloadEffects, DownloadEffects,
ViewerEffects, ViewerEffects,
SearchEffects SearchEffects,
SiteEffects
} from './effects'; } from './effects';
@NgModule({ @NgModule({
@@ -53,7 +54,8 @@ import {
RouterEffects, RouterEffects,
DownloadEffects, DownloadEffects,
ViewerEffects, ViewerEffects,
SearchEffects SearchEffects,
SiteEffects
]), ]),
!environment.production !environment.production
? StoreDevtoolsModule.instrument({ maxAge: 25 }) ? StoreDevtoolsModule.instrument({ maxAge: 25 })

View File

@@ -29,3 +29,4 @@ export * from './effects/router.effects';
export * from './effects/snackbar.effects'; export * from './effects/snackbar.effects';
export * from './effects/viewer.effects'; export * from './effects/viewer.effects';
export * from './effects/search.effects'; export * from './effects/search.effects';
export * from './effects/library.effects';

View File

@@ -0,0 +1,71 @@
/*!
* @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 { Effect, Actions, ofType } from '@ngrx/effects';
import { Injectable } from '@angular/core';
import { map } from 'rxjs/operators';
import { DeleteLibraryAction, DELETE_LIBRARY } from '../actions';
import { AlfrescoApiService } from '@alfresco/adf-core';
import {
SnackbarInfoAction,
SnackbarErrorAction
} from '../actions/snackbar.actions';
import { Store } from '@ngrx/store';
import { AppStore } from '../states/app.state';
import { ContentManagementService } from '../../common/services/content-management.service';
@Injectable()
export class SiteEffects {
constructor(
private actions$: Actions,
private store: Store<AppStore>,
private apiService: AlfrescoApiService,
private content: ContentManagementService
) {}
@Effect({ dispatch: false })
deleteLibrary$ = this.actions$.pipe(
ofType<DeleteLibraryAction>(DELETE_LIBRARY),
map(action => {
this.apiService.sitesApi.deleteSite(action.payload).then(
() => {
this.content.siteDeleted.next(action.payload);
this.store.dispatch(
new SnackbarInfoAction(
'APP.MESSAGES.INFO.LIBRARY_DELETED'
)
);
},
err => {
this.store.dispatch(
new SnackbarErrorAction(
'APP.MESSAGES.ERRORS.DELETE_LIBRARY_FAILED'
)
);
}
);
})
);
}

View File

@@ -174,7 +174,8 @@
"LOCATION_MISSING": "Can't restore {{ name }}, the original location no longer exists", "LOCATION_MISSING": "Can't restore {{ name }}, the original location no longer exists",
"GENERIC": "There was a problem restoring {{ name }}" "GENERIC": "There was a problem restoring {{ name }}"
} }
} },
"DELETE_LIBRARY_FAILED": "Cannot delete the library"
}, },
"UPLOAD": { "UPLOAD": {
"ERROR": { "ERROR": {
@@ -218,7 +219,8 @@
"PLURAL": "Partially moved {{ partially }} items.", "PLURAL": "Partially moved {{ partially }} items.",
"FAIL": "{{ failed }} couldn't be moved." "FAIL": "{{ failed }} couldn't be moved."
} }
} },
"LIBRARY_DELETED": "Library deleted"
} }
}, },
"CONTENT_METADATA": { "CONTENT_METADATA": {