mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-31 17:38:28 +00:00
[ACA-1631] more application ngrx actions (#540)
* delete action * library path evaluator * extension for sharing files * upload actions * delete library * use extensions for experimental library actions * unshare nodes * fix icons and titles * "create menu" backed by core extension * support for descriptions, update upload selector * update code and tests * support disabled tooltips for navbar * fix selector * [ACA-1486] remove double fetch call * migrate to trashcan actions, element IDs * cleanup code, remove deprecated directives * add/remove favorite * improve rendering performance * update favorites without reload * support for adding Sites to favorites * disable favorites for Libraries for now * copy action * move node * manage versions and permissions * cleanup code * toggle info drawer * card view mode * use extension layer for favorites toolbar * fix menu tooltips * fix 'remove as favorite' tests * update tests * test fixes * fix edit folder for favorites * fix test * cleanup favorites layout * upgrade recent files layout * update evaluators for shared nodes * test fixes * test fixes * restore recent files layout * workaround for "favorite" toggle and recent files * upgrade shared files page * upgrade files page layout * fix library evaluator * workaround for shared files and permissions * cleanup code * upgrade search results * upgrade sidebar and viewer actions * code cleanup * code cleanup * code cleanup
This commit is contained in:
82
src/app/store/effects/favorite.effects.ts
Normal file
82
src/app/store/effects/favorite.effects.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
/*!
|
||||
* @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 { ADD_FAVORITE, AddFavoriteAction, RemoveFavoriteAction, REMOVE_FAVORITE } from '../actions/favorite.actions';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppStore } from '../states';
|
||||
import { appSelection } from '../selectors/app.selectors';
|
||||
import { ContentManagementService } from '../../services/content-management.service';
|
||||
|
||||
@Injectable()
|
||||
export class FavoriteEffects {
|
||||
constructor(
|
||||
private store: Store<AppStore>,
|
||||
private actions$: Actions,
|
||||
private content: ContentManagementService
|
||||
) {}
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
addFavorite$ = this.actions$.pipe(
|
||||
ofType<AddFavoriteAction>(ADD_FAVORITE),
|
||||
map(action => {
|
||||
if (action.payload && action.payload.length > 0) {
|
||||
this.content.addFavorite(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.take(1)
|
||||
.subscribe(selection => {
|
||||
if (selection && !selection.isEmpty) {
|
||||
this.content.addFavorite(selection.nodes);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
removeFavorite$ = this.actions$.pipe(
|
||||
ofType<RemoveFavoriteAction>(REMOVE_FAVORITE),
|
||||
map(action => {
|
||||
if (action.payload && action.payload.length > 0) {
|
||||
this.content.removeFavorite(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.take(1)
|
||||
.subscribe(selection => {
|
||||
if (selection && !selection.isEmpty) {
|
||||
this.content.removeFavorite(selection.nodes);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
}
|
@@ -30,21 +30,16 @@ import {
|
||||
DeleteLibraryAction, DELETE_LIBRARY,
|
||||
CreateLibraryAction, CREATE_LIBRARY
|
||||
} from '../actions';
|
||||
import {
|
||||
SnackbarInfoAction,
|
||||
SnackbarErrorAction
|
||||
} from '../actions/snackbar.actions';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppStore } from '../states/app.state';
|
||||
import { ContentManagementService } from '../../services/content-management.service';
|
||||
import { ContentApiService } from '../../services/content-api.service';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppStore } from '../states';
|
||||
import { appSelection } from '../selectors/app.selectors';
|
||||
|
||||
@Injectable()
|
||||
export class SiteEffects {
|
||||
constructor(
|
||||
private actions$: Actions,
|
||||
private store: Store<AppStore>,
|
||||
private contentApi: ContentApiService,
|
||||
private actions$: Actions,
|
||||
private content: ContentManagementService
|
||||
) {}
|
||||
|
||||
@@ -53,7 +48,16 @@ export class SiteEffects {
|
||||
ofType<DeleteLibraryAction>(DELETE_LIBRARY),
|
||||
map(action => {
|
||||
if (action.payload) {
|
||||
this.deleteLibrary(action.payload);
|
||||
this.content.deleteLibrary(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.take(1)
|
||||
.subscribe(selection => {
|
||||
if (selection && selection.library) {
|
||||
this.content.deleteLibrary(selection.library.entry.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
@@ -62,31 +66,7 @@ export class SiteEffects {
|
||||
createLibrary$ = this.actions$.pipe(
|
||||
ofType<CreateLibraryAction>(CREATE_LIBRARY),
|
||||
map(action => {
|
||||
this.createLibrary();
|
||||
this.content.createLibrary();
|
||||
})
|
||||
);
|
||||
|
||||
private deleteLibrary(id: string) {
|
||||
this.contentApi.deleteSite(id).subscribe(
|
||||
() => {
|
||||
this.content.libraryDeleted.next(id);
|
||||
this.store.dispatch(
|
||||
new SnackbarInfoAction(
|
||||
'APP.MESSAGES.INFO.LIBRARY_DELETED'
|
||||
)
|
||||
);
|
||||
},
|
||||
() => {
|
||||
this.store.dispatch(
|
||||
new SnackbarErrorAction(
|
||||
'APP.MESSAGES.ERRORS.DELETE_LIBRARY_FAILED'
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private createLibrary() {
|
||||
this.content.createLibrary();
|
||||
}
|
||||
}
|
||||
|
@@ -29,49 +29,97 @@ import { map } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppStore } from '../states/app.state';
|
||||
import {
|
||||
SnackbarWarningAction,
|
||||
SnackbarInfoAction,
|
||||
SnackbarErrorAction,
|
||||
PurgeDeletedNodesAction,
|
||||
PURGE_DELETED_NODES,
|
||||
DeleteNodesAction,
|
||||
DELETE_NODES,
|
||||
SnackbarUserAction,
|
||||
SnackbarAction,
|
||||
UndoDeleteNodesAction,
|
||||
UNDO_DELETE_NODES,
|
||||
CreateFolderAction,
|
||||
CREATE_FOLDER
|
||||
CREATE_FOLDER,
|
||||
EditFolderAction,
|
||||
EDIT_FOLDER,
|
||||
RestoreDeletedNodesAction,
|
||||
RESTORE_DELETED_NODES,
|
||||
ShareNodeAction,
|
||||
SHARE_NODE
|
||||
} from '../actions';
|
||||
import { ContentManagementService } from '../../services/content-management.service';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { NodeInfo, DeleteStatus, DeletedNodeInfo } from '../models';
|
||||
import { ContentApiService } from '../../services/content-api.service';
|
||||
import { currentFolder, appSelection } from '../selectors/app.selectors';
|
||||
import { EditFolderAction, EDIT_FOLDER, RestoreDeletedNodesAction, RESTORE_DELETED_NODES } from '../actions/node.actions';
|
||||
import {
|
||||
UnshareNodesAction,
|
||||
UNSHARE_NODES,
|
||||
CopyNodesAction,
|
||||
COPY_NODES,
|
||||
MoveNodesAction,
|
||||
MOVE_NODES,
|
||||
ManagePermissionsAction,
|
||||
MANAGE_PERMISSIONS,
|
||||
ManageVersionsAction,
|
||||
MANAGE_VERSIONS
|
||||
} from '../actions/node.actions';
|
||||
|
||||
@Injectable()
|
||||
export class NodeEffects {
|
||||
constructor(
|
||||
private store: Store<AppStore>,
|
||||
private actions$: Actions,
|
||||
private contentManagementService: ContentManagementService,
|
||||
private contentApi: ContentApiService
|
||||
private contentService: ContentManagementService
|
||||
) {}
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
shareNode$ = this.actions$.pipe(
|
||||
ofType<ShareNodeAction>(SHARE_NODE),
|
||||
map(action => {
|
||||
if (action.payload) {
|
||||
this.contentService.shareNode(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.take(1)
|
||||
.subscribe(selection => {
|
||||
if (selection && selection.file) {
|
||||
this.contentService.shareNode(selection.file);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
unshareNodes$ = this.actions$.pipe(
|
||||
ofType<UnshareNodesAction>(UNSHARE_NODES),
|
||||
map(action => {
|
||||
if (action && action.payload && action.payload.length > 0) {
|
||||
this.contentService.unshareNodes(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.take(1)
|
||||
.subscribe(selection => {
|
||||
if (selection && !selection.isEmpty) {
|
||||
this.contentService.unshareNodes(selection.nodes);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
purgeDeletedNodes$ = this.actions$.pipe(
|
||||
ofType<PurgeDeletedNodesAction>(PURGE_DELETED_NODES),
|
||||
map(action => {
|
||||
if (action && action.payload && action.payload.length > 0) {
|
||||
this.contentManagementService.purgeDeletedNodes(action.payload);
|
||||
this.contentService.purgeDeletedNodes(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.take(1)
|
||||
.subscribe(selection => {
|
||||
if (selection && selection.count > 0) {
|
||||
this.contentManagementService.purgeDeletedNodes(selection.nodes);
|
||||
this.contentService.purgeDeletedNodes(
|
||||
selection.nodes
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -83,14 +131,16 @@ export class NodeEffects {
|
||||
ofType<RestoreDeletedNodesAction>(RESTORE_DELETED_NODES),
|
||||
map(action => {
|
||||
if (action && action.payload && action.payload.length > 0) {
|
||||
this.contentManagementService.restoreDeletedNodes(action.payload);
|
||||
this.contentService.restoreDeletedNodes(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.take(1)
|
||||
.subscribe(selection => {
|
||||
if (selection && selection.count > 0) {
|
||||
this.contentManagementService.restoreDeletedNodes(selection.nodes);
|
||||
this.contentService.restoreDeletedNodes(
|
||||
selection.nodes
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -101,8 +151,17 @@ export class NodeEffects {
|
||||
deleteNodes$ = this.actions$.pipe(
|
||||
ofType<DeleteNodesAction>(DELETE_NODES),
|
||||
map(action => {
|
||||
if (action.payload.length > 0) {
|
||||
this.deleteNodes(action.payload);
|
||||
if (action && action.payload && action.payload.length > 0) {
|
||||
this.contentService.deleteNodes(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.take(1)
|
||||
.subscribe(selection => {
|
||||
if (selection && selection.count > 0) {
|
||||
this.contentService.deleteNodes(selection.nodes);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
@@ -112,7 +171,7 @@ export class NodeEffects {
|
||||
ofType<UndoDeleteNodesAction>(UNDO_DELETE_NODES),
|
||||
map(action => {
|
||||
if (action.payload.length > 0) {
|
||||
this.undoDeleteNodes(action.payload);
|
||||
this.contentService.undoDeleteNodes(action.payload);
|
||||
}
|
||||
})
|
||||
);
|
||||
@@ -122,14 +181,14 @@ export class NodeEffects {
|
||||
ofType<CreateFolderAction>(CREATE_FOLDER),
|
||||
map(action => {
|
||||
if (action.payload) {
|
||||
this.contentManagementService.createFolder(action.payload);
|
||||
this.contentService.createFolder(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(currentFolder)
|
||||
.take(1)
|
||||
.subscribe(node => {
|
||||
if (node && node.id) {
|
||||
this.contentManagementService.createFolder(node.id);
|
||||
this.contentService.createFolder(node.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -141,215 +200,97 @@ export class NodeEffects {
|
||||
ofType<EditFolderAction>(EDIT_FOLDER),
|
||||
map(action => {
|
||||
if (action.payload) {
|
||||
this.contentManagementService.editFolder(action.payload);
|
||||
this.contentService.editFolder(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.take(1)
|
||||
.subscribe(selection => {
|
||||
if (selection && selection.folder) {
|
||||
this.contentManagementService.editFolder(selection.folder);
|
||||
this.contentService.editFolder(selection.folder);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
private deleteNodes(items: NodeInfo[]): void {
|
||||
const batch: Observable<DeletedNodeInfo>[] = [];
|
||||
|
||||
items.forEach(node => {
|
||||
batch.push(this.deleteNode(node));
|
||||
});
|
||||
|
||||
Observable.forkJoin(...batch).subscribe((data: DeletedNodeInfo[]) => {
|
||||
const status = this.processStatus(data);
|
||||
const message = this.getDeleteMessage(status);
|
||||
|
||||
if (message && status.someSucceeded) {
|
||||
message.duration = 10000;
|
||||
message.userAction = new SnackbarUserAction(
|
||||
'APP.ACTIONS.UNDO',
|
||||
new UndoDeleteNodesAction([...status.success])
|
||||
);
|
||||
}
|
||||
|
||||
this.store.dispatch(message);
|
||||
|
||||
if (status.someSucceeded) {
|
||||
this.contentManagementService.nodesDeleted.next();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private deleteNode(node: NodeInfo): Observable<DeletedNodeInfo> {
|
||||
const { id, name } = node;
|
||||
|
||||
return this.contentApi
|
||||
.deleteNode(id)
|
||||
.map(() => {
|
||||
return {
|
||||
id,
|
||||
name,
|
||||
status: 1
|
||||
};
|
||||
})
|
||||
.catch((error: any) => {
|
||||
return Observable.of({
|
||||
id,
|
||||
name,
|
||||
status: 0
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private getDeleteMessage(status: DeleteStatus): SnackbarAction {
|
||||
if (status.allFailed && !status.oneFailed) {
|
||||
return new SnackbarErrorAction(
|
||||
'APP.MESSAGES.ERRORS.NODE_DELETION_PLURAL',
|
||||
{ number: status.fail.length }
|
||||
);
|
||||
}
|
||||
|
||||
if (status.allSucceeded && !status.oneSucceeded) {
|
||||
return new SnackbarInfoAction(
|
||||
'APP.MESSAGES.INFO.NODE_DELETION.PLURAL',
|
||||
{ number: status.success.length }
|
||||
);
|
||||
}
|
||||
|
||||
if (status.someFailed && status.someSucceeded && !status.oneSucceeded) {
|
||||
return new SnackbarWarningAction(
|
||||
'APP.MESSAGES.INFO.NODE_DELETION.PARTIAL_PLURAL',
|
||||
{
|
||||
success: status.success.length,
|
||||
failed: status.fail.length
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (status.someFailed && status.oneSucceeded) {
|
||||
return new SnackbarWarningAction(
|
||||
'APP.MESSAGES.INFO.NODE_DELETION.PARTIAL_SINGULAR',
|
||||
{
|
||||
success: status.success.length,
|
||||
failed: status.fail.length
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (status.oneFailed && !status.someSucceeded) {
|
||||
return new SnackbarErrorAction(
|
||||
'APP.MESSAGES.ERRORS.NODE_DELETION',
|
||||
{ name: status.fail[0].name }
|
||||
);
|
||||
}
|
||||
|
||||
if (status.oneSucceeded && !status.someFailed) {
|
||||
return new SnackbarInfoAction(
|
||||
'APP.MESSAGES.INFO.NODE_DELETION.SINGULAR',
|
||||
{ name: status.success[0].name }
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private undoDeleteNodes(items: DeletedNodeInfo[]): void {
|
||||
const batch: Observable<DeletedNodeInfo>[] = [];
|
||||
|
||||
items.forEach(item => {
|
||||
batch.push(this.undoDeleteNode(item));
|
||||
});
|
||||
|
||||
Observable.forkJoin(...batch).subscribe(data => {
|
||||
const processedData = this.processStatus(data);
|
||||
|
||||
if (processedData.fail.length) {
|
||||
const message = this.getUndoDeleteMessage(processedData);
|
||||
this.store.dispatch(message);
|
||||
}
|
||||
|
||||
if (processedData.someSucceeded) {
|
||||
this.contentManagementService.nodesRestored.next();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private undoDeleteNode(item: DeletedNodeInfo): Observable<DeletedNodeInfo> {
|
||||
const { id, name } = item;
|
||||
|
||||
return this.contentApi
|
||||
.restoreNode(id)
|
||||
.map(() => {
|
||||
return {
|
||||
id,
|
||||
name,
|
||||
status: 1
|
||||
};
|
||||
})
|
||||
.catch((error: any) => {
|
||||
return Observable.of({
|
||||
id,
|
||||
name,
|
||||
status: 0
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private getUndoDeleteMessage(status: DeleteStatus): SnackbarAction {
|
||||
if (status.someFailed && !status.oneFailed) {
|
||||
return new SnackbarErrorAction(
|
||||
'APP.MESSAGES.ERRORS.NODE_RESTORE_PLURAL',
|
||||
{ number: status.fail.length }
|
||||
);
|
||||
}
|
||||
|
||||
if (status.oneFailed) {
|
||||
return new SnackbarErrorAction('APP.MESSAGES.ERRORS.NODE_RESTORE', {
|
||||
name: status.fail[0].name
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private processStatus(data: DeletedNodeInfo[] = []): DeleteStatus {
|
||||
const status = {
|
||||
fail: [],
|
||||
success: [],
|
||||
get someFailed() {
|
||||
return !!this.fail.length;
|
||||
},
|
||||
get someSucceeded() {
|
||||
return !!this.success.length;
|
||||
},
|
||||
get oneFailed() {
|
||||
return this.fail.length === 1;
|
||||
},
|
||||
get oneSucceeded() {
|
||||
return this.success.length === 1;
|
||||
},
|
||||
get allSucceeded() {
|
||||
return this.someSucceeded && !this.someFailed;
|
||||
},
|
||||
get allFailed() {
|
||||
return this.someFailed && !this.someSucceeded;
|
||||
},
|
||||
reset() {
|
||||
this.fail = [];
|
||||
this.success = [];
|
||||
}
|
||||
};
|
||||
|
||||
return data.reduce((acc, node) => {
|
||||
if (node.status) {
|
||||
acc.success.push(node);
|
||||
@Effect({ dispatch: false })
|
||||
copyNodes$ = this.actions$.pipe(
|
||||
ofType<CopyNodesAction>(COPY_NODES),
|
||||
map(action => {
|
||||
if (action.payload && action.payload.length > 0) {
|
||||
this.contentService.copyNodes(action.payload);
|
||||
} else {
|
||||
acc.fail.push(node);
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.take(1)
|
||||
.subscribe(selection => {
|
||||
if (selection && !selection.isEmpty) {
|
||||
this.contentService.copyNodes(selection.nodes);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
return acc;
|
||||
}, status);
|
||||
}
|
||||
@Effect({ dispatch: false })
|
||||
moveNodes$ = this.actions$.pipe(
|
||||
ofType<MoveNodesAction>(MOVE_NODES),
|
||||
map(action => {
|
||||
if (action.payload && action.payload.length > 0) {
|
||||
this.contentService.moveNodes(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.take(1)
|
||||
.subscribe(selection => {
|
||||
if (selection && !selection.isEmpty) {
|
||||
this.contentService.moveNodes(selection.nodes);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
managePermissions = this.actions$.pipe(
|
||||
ofType<ManagePermissionsAction>(MANAGE_PERMISSIONS),
|
||||
map(action => {
|
||||
if (action && action.payload) {
|
||||
this.contentService.managePermissions(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.take(1)
|
||||
.subscribe(selection => {
|
||||
if (selection && !selection.isEmpty) {
|
||||
this.contentService.managePermissions(
|
||||
selection.first
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
manageVersions$ = this.actions$.pipe(
|
||||
ofType<ManageVersionsAction>(MANAGE_VERSIONS),
|
||||
map(action => {
|
||||
if (action && action.payload) {
|
||||
this.contentService.manageVersions(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.take(1)
|
||||
.subscribe(selection => {
|
||||
if (selection && selection.file) {
|
||||
this.contentService.manageVersions(
|
||||
selection.file
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
116
src/app/store/effects/upload.effects.ts
Normal file
116
src/app/store/effects/upload.effects.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
/*!
|
||||
* @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 { Injectable, RendererFactory2, NgZone } from '@angular/core';
|
||||
import { Actions, Effect, ofType } from '@ngrx/effects';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppStore } from '../states';
|
||||
import { UploadFilesAction, UPLOAD_FILES } from '../actions';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { FileUtils, FileModel, UploadService } from '@alfresco/adf-core';
|
||||
import { currentFolder } from '../selectors/app.selectors';
|
||||
import { UploadFolderAction, UPLOAD_FOLDER } from '../actions/upload.actions';
|
||||
|
||||
@Injectable()
|
||||
export class UploadEffects {
|
||||
private fileInput: HTMLInputElement;
|
||||
private folderInput: HTMLInputElement;
|
||||
|
||||
constructor(
|
||||
private store: Store<AppStore>,
|
||||
private actions$: Actions,
|
||||
private ngZone: NgZone,
|
||||
private uploadService: UploadService,
|
||||
rendererFactory: RendererFactory2
|
||||
) {
|
||||
const renderer = rendererFactory.createRenderer(null, null);
|
||||
|
||||
this.fileInput = renderer.createElement('input') as HTMLInputElement;
|
||||
this.fileInput.id = 'app-upload-files';
|
||||
this.fileInput.type = 'file';
|
||||
this.fileInput.style.display = 'none';
|
||||
this.fileInput.setAttribute('multiple', '');
|
||||
this.fileInput.addEventListener('change', event => this.upload(event));
|
||||
renderer.appendChild(document.body, this.fileInput);
|
||||
|
||||
|
||||
this.folderInput = renderer.createElement('input') as HTMLInputElement;
|
||||
this.folderInput.id = 'app-upload-folder';
|
||||
this.folderInput.type = 'file';
|
||||
this.folderInput.style.display = 'none';
|
||||
this.folderInput.setAttribute('directory', '');
|
||||
this.folderInput.setAttribute('webkitdirectory', '');
|
||||
this.folderInput.addEventListener('change', event => this.upload(event));
|
||||
renderer.appendChild(document.body, this.folderInput);
|
||||
}
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
uploadFiles$ = this.actions$.pipe(
|
||||
ofType<UploadFilesAction>(UPLOAD_FILES),
|
||||
map(() => {
|
||||
this.fileInput.click();
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
uploadFolder$ = this.actions$.pipe(
|
||||
ofType<UploadFolderAction>(UPLOAD_FOLDER),
|
||||
map(() => {
|
||||
this.folderInput.click();
|
||||
})
|
||||
);
|
||||
|
||||
private upload(event: any): void {
|
||||
this.store
|
||||
.select(currentFolder)
|
||||
.take(1)
|
||||
.subscribe(node => {
|
||||
if (node && node.id) {
|
||||
const input = <HTMLInputElement>event.currentTarget;
|
||||
const files = FileUtils.toFileArray(input.files).map(
|
||||
file => {
|
||||
return new FileModel(file, {
|
||||
parentId: node.id,
|
||||
path: (file.webkitRelativePath || '').replace(/\/[^\/]*$/, ''),
|
||||
nodeType: 'cm:content'
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
this.uploadQueue(files);
|
||||
event.target.value = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private uploadQueue(files: FileModel[]) {
|
||||
if (files.length > 0) {
|
||||
this.ngZone.run(() => {
|
||||
this.uploadService.addToQueue(...files);
|
||||
this.uploadService.uploadFilesInTheQueue();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user