mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-31 17:38:28 +00:00
[ACA-1532] make Preview command available to extensions (#502)
* view file action and effect * integrate view action with search input/row * deprecate old ViewNode action/effect * preview file command as extension * reorder commands
This commit is contained in:
@@ -70,6 +70,11 @@
|
|||||||
"type": "DOWNLOAD_NODES",
|
"type": "DOWNLOAD_NODES",
|
||||||
"payload": null
|
"payload": null
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "aca:actions/preview",
|
||||||
|
"type": "VIEW_FILE",
|
||||||
|
"payload": null
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"id": "aca:actions/info",
|
"id": "aca:actions/info",
|
||||||
@@ -206,6 +211,18 @@
|
|||||||
"action": "aca:actions/create-folder"
|
"action": "aca:actions/create-folder"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"id": "aca:toolbar/preview",
|
||||||
|
"order": 15,
|
||||||
|
"title": "APP.ACTIONS.VIEW",
|
||||||
|
"icon": "open_in_browser",
|
||||||
|
"target": {
|
||||||
|
"types": ["file"],
|
||||||
|
"permissions": [],
|
||||||
|
"action": "aca:actions/preview"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"disabled": false,
|
"disabled": false,
|
||||||
"id": "aca:toolbar/download",
|
"id": "aca:toolbar/download",
|
||||||
|
@@ -30,7 +30,7 @@ import { Store } from '@ngrx/store';
|
|||||||
import { MinimalNodeEntity, MinimalNodeEntryEntity } from 'alfresco-js-api';
|
import { MinimalNodeEntity, MinimalNodeEntryEntity } from 'alfresco-js-api';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
import { Subject, Subscription } from 'rxjs/Rx';
|
import { Subject, Subscription } from 'rxjs/Rx';
|
||||||
import { ViewNodeAction, SetSelectedNodesAction, DownloadNodesAction } from '../store/actions';
|
import { SetSelectedNodesAction, DownloadNodesAction, ViewFileAction } from '../store/actions';
|
||||||
import { appSelection, sharedUrl, currentFolder } from '../store/selectors/app.selectors';
|
import { appSelection, sharedUrl, currentFolder } from '../store/selectors/app.selectors';
|
||||||
import { AppStore } from '../store/states/app.state';
|
import { AppStore } from '../store/states/app.state';
|
||||||
import { SelectionState } from '../store/states/selection.state';
|
import { SelectionState } from '../store/states/selection.state';
|
||||||
@@ -109,16 +109,8 @@ export abstract class PageComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
showPreview(node: MinimalNodeEntity) {
|
showPreview(node: MinimalNodeEntity) {
|
||||||
if (node && node.entry) {
|
if (node && node.entry) {
|
||||||
const { id, nodeId, name, isFile, isFolder } = node.entry;
|
|
||||||
const parentId = this.node ? this.node.id : null;
|
const parentId = this.node ? this.node.id : null;
|
||||||
|
this.store.dispatch(new ViewFileAction(node, parentId));
|
||||||
this.store.dispatch(new ViewNodeAction({
|
|
||||||
parentId,
|
|
||||||
id: nodeId || id,
|
|
||||||
name,
|
|
||||||
isFile,
|
|
||||||
isFolder
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@ import { TestBed, async, ComponentFixture, fakeAsync, tick } from '@angular/core
|
|||||||
import { SearchInputComponent } from './search-input.component';
|
import { SearchInputComponent } from './search-input.component';
|
||||||
import { AppTestingModule } from '../../../testing/app-testing.module';
|
import { AppTestingModule } from '../../../testing/app-testing.module';
|
||||||
import { Actions, ofType } from '@ngrx/effects';
|
import { Actions, ofType } from '@ngrx/effects';
|
||||||
import { ViewNodeAction, VIEW_NODE, NAVIGATE_FOLDER, NavigateToFolder } from '../../../store/actions';
|
import { NAVIGATE_FOLDER, NavigateToFolder, VIEW_FILE, ViewFileAction } from '../../../store/actions';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
describe('SearchInputComponent', () => {
|
describe('SearchInputComponent', () => {
|
||||||
@@ -59,9 +59,9 @@ describe('SearchInputComponent', () => {
|
|||||||
describe('onItemClicked()', () => {
|
describe('onItemClicked()', () => {
|
||||||
it('opens preview if node is file', fakeAsync(done => {
|
it('opens preview if node is file', fakeAsync(done => {
|
||||||
actions$.pipe(
|
actions$.pipe(
|
||||||
ofType<ViewNodeAction>(VIEW_NODE),
|
ofType<ViewFileAction>(VIEW_FILE),
|
||||||
map(action => {
|
map(action => {
|
||||||
expect(action.payload.id).toBe('node-id');
|
expect(action.payload.entry.id).toBe('node-id');
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@@ -32,7 +32,7 @@ import { MinimalNodeEntity } from 'alfresco-js-api';
|
|||||||
import { SearchInputControlComponent } from '../search-input-control/search-input-control.component';
|
import { SearchInputControlComponent } from '../search-input-control/search-input-control.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 { SearchByTermAction, ViewNodeAction, NavigateToFolder } from '../../../store/actions';
|
import { SearchByTermAction, NavigateToFolder, ViewFileAction } from '../../../store/actions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'aca-search-input',
|
selector: 'aca-search-input',
|
||||||
@@ -90,15 +90,9 @@ export class SearchInputComponent implements OnInit {
|
|||||||
|
|
||||||
onItemClicked(node: MinimalNodeEntity) {
|
onItemClicked(node: MinimalNodeEntity) {
|
||||||
if (node && node.entry) {
|
if (node && node.entry) {
|
||||||
const { id, nodeId, name, isFile, isFolder, parentId } = node.entry;
|
const { isFile, isFolder } = node.entry;
|
||||||
if (isFile) {
|
if (isFile) {
|
||||||
this.store.dispatch(new ViewNodeAction({
|
this.store.dispatch(new ViewFileAction(node));
|
||||||
parentId,
|
|
||||||
id: nodeId || id,
|
|
||||||
name,
|
|
||||||
isFile,
|
|
||||||
isFolder
|
|
||||||
}));
|
|
||||||
} else if (isFolder) {
|
} else if (isFolder) {
|
||||||
this.store.dispatch(new NavigateToFolder(node));
|
this.store.dispatch(new NavigateToFolder(node));
|
||||||
}
|
}
|
||||||
|
@@ -24,8 +24,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, Input, OnInit, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/core';
|
import { Component, Input, OnInit, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/core';
|
||||||
import { MinimalNodeEntryEntity } from 'alfresco-js-api';
|
import { MinimalNodeEntity } from 'alfresco-js-api';
|
||||||
import { ViewNodeAction } from '../../../store/actions/viewer.actions';
|
import { ViewFileAction } from '../../../store/actions';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { AppStore } from '../../../store/states/app.state';
|
import { AppStore } from '../../../store/states/app.state';
|
||||||
|
|
||||||
@@ -38,14 +38,14 @@ import { AppStore } from '../../../store/states/app.state';
|
|||||||
host: { class: 'aca-search-results-row' }
|
host: { class: 'aca-search-results-row' }
|
||||||
})
|
})
|
||||||
export class SearchResultsRowComponent implements OnInit {
|
export class SearchResultsRowComponent implements OnInit {
|
||||||
private node: MinimalNodeEntryEntity;
|
private node: MinimalNodeEntity;
|
||||||
|
|
||||||
@Input() context: any;
|
@Input() context: any;
|
||||||
|
|
||||||
constructor(private store: Store<AppStore>) {}
|
constructor(private store: Store<AppStore>) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.node = this.context.row.node.entry;
|
this.node = this.context.row.node;
|
||||||
}
|
}
|
||||||
|
|
||||||
get name() {
|
get name() {
|
||||||
@@ -89,13 +89,8 @@ export class SearchResultsRowComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showPreview() {
|
showPreview() {
|
||||||
const { id, name } = this.node;
|
|
||||||
|
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
new ViewNodeAction({
|
new ViewFileAction(this.node)
|
||||||
id,
|
|
||||||
name
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +101,6 @@ export class SearchResultsRowComponent implements OnInit {
|
|||||||
.replace('[', '.')
|
.replace('[', '.')
|
||||||
.replace(']', '')
|
.replace(']', '')
|
||||||
.split('.')
|
.split('.')
|
||||||
.reduce((acc, part) => (acc ? acc[part] : null), this.node);
|
.reduce((acc, part) => (acc ? acc[part] : null), this.node.entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,11 +24,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
import { NodeInfo } from '../models';
|
import { MinimalNodeEntity } from 'alfresco-js-api';
|
||||||
|
|
||||||
export const VIEW_NODE = 'VIEW_NODE';
|
export const VIEW_FILE = 'VIEW_FILE';
|
||||||
|
|
||||||
export class ViewNodeAction implements Action {
|
export class ViewFileAction implements Action {
|
||||||
readonly type = VIEW_NODE;
|
readonly type = VIEW_FILE;
|
||||||
constructor(public payload: NodeInfo) {}
|
constructor(public payload: MinimalNodeEntity, public parentId?: string) {}
|
||||||
}
|
}
|
||||||
|
@@ -26,19 +26,67 @@
|
|||||||
import { Effect, Actions, ofType } from '@ngrx/effects';
|
import { Effect, Actions, ofType } from '@ngrx/effects';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { ViewNodeAction, VIEW_NODE } from '../actions/viewer.actions';
|
import { VIEW_FILE, ViewFileAction } from '../actions';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
import { Store, createSelector } from '@ngrx/store';
|
||||||
|
import { AppStore } from '../states';
|
||||||
|
import { appSelection, currentFolder } from '../selectors/app.selectors';
|
||||||
|
|
||||||
|
export const fileToPreview = createSelector(
|
||||||
|
appSelection,
|
||||||
|
currentFolder,
|
||||||
|
(selection, folder) => {
|
||||||
|
return {
|
||||||
|
selection,
|
||||||
|
folder
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ViewerEffects {
|
export class ViewerEffects {
|
||||||
constructor(private actions$: Actions, private router: Router) {}
|
constructor(
|
||||||
|
private store: Store<AppStore>,
|
||||||
|
private actions$: Actions,
|
||||||
|
private router: Router
|
||||||
|
) {}
|
||||||
|
|
||||||
@Effect({ dispatch: false })
|
@Effect({ dispatch: false })
|
||||||
viewNode$ = this.actions$.pipe(
|
viewFile$ = this.actions$.pipe(
|
||||||
ofType<ViewNodeAction>(VIEW_NODE),
|
ofType<ViewFileAction>(VIEW_FILE),
|
||||||
map(action => {
|
map(action => {
|
||||||
const node = action.payload;
|
if (action.payload && action.payload.entry) {
|
||||||
if (!node) {
|
const { id, nodeId, isFile } = action.payload.entry;
|
||||||
|
|
||||||
|
if (isFile || nodeId) {
|
||||||
|
this.displayPreview(nodeId || id, action.parentId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.store
|
||||||
|
.select(fileToPreview)
|
||||||
|
.take(1)
|
||||||
|
.subscribe(result => {
|
||||||
|
if (result.selection && result.selection.file) {
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
nodeId,
|
||||||
|
isFile
|
||||||
|
} = result.selection.file.entry;
|
||||||
|
|
||||||
|
if (isFile || nodeId) {
|
||||||
|
const parentId = result.folder
|
||||||
|
? result.folder.id
|
||||||
|
: null;
|
||||||
|
this.displayPreview(nodeId || id, parentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
private displayPreview(nodeId: string, parentId: string) {
|
||||||
|
if (!nodeId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,11 +100,10 @@ export class ViewerEffects {
|
|||||||
previewLocation = previewLocation.replace(/\//g, '');
|
previewLocation = previewLocation.replace(/\//g, '');
|
||||||
|
|
||||||
const path = [previewLocation];
|
const path = [previewLocation];
|
||||||
if (node.parentId) {
|
if (parentId) {
|
||||||
path.push(node.parentId);
|
path.push(parentId);
|
||||||
}
|
}
|
||||||
path.push('preview', node.id);
|
path.push('preview', nodeId);
|
||||||
this.router.navigateByUrl(path.join('/'));
|
this.router.navigateByUrl(path.join('/'));
|
||||||
})
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user