mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
added functionality to view a previous version (#5913)
This commit is contained in:
@@ -74,6 +74,19 @@ export const appRoutes: Routes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'files/:nodeId/:versionId/view',
|
||||
component: AppComponent,
|
||||
canActivate: [AuthGuardEcm],
|
||||
canActivateChild: [AuthGuardEcm],
|
||||
outlet: 'overlay',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
loadChildren: () => import('./components/file-view/file-view.module').then(m => m.FileViewModule)
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'preview/blob',
|
||||
component: AppComponent,
|
||||
|
@@ -108,7 +108,8 @@
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<adf-version-manager [node]="node"
|
||||
(uploadError)="onUploadError($event)">
|
||||
(uploadError)="onUploadError($event)"
|
||||
(viewVersion)="onViewVersion($event)">
|
||||
</adf-version-manager>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -318,6 +319,7 @@
|
||||
<adf-viewer
|
||||
[blobFile]="content"
|
||||
[nodeId]="nodeId"
|
||||
[versionId]="versionId"
|
||||
[showRightSidebar]="showRightSidebar"
|
||||
[showLeftSidebar]="showLeftSidebar"
|
||||
[allowGoBack]="allowGoBack"
|
||||
|
@@ -30,6 +30,7 @@ import { PreviewService } from '../../services/preview.service';
|
||||
export class FileViewComponent implements OnInit {
|
||||
|
||||
nodeId: string = null;
|
||||
versionId: string = null;
|
||||
displayEmptyMetadata = false;
|
||||
expanded: boolean;
|
||||
multi = false;
|
||||
@@ -72,6 +73,7 @@ export class FileViewComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
this.route.params.subscribe((params) => {
|
||||
const id = params.nodeId;
|
||||
this.versionId = params.versionId;
|
||||
if (id) {
|
||||
this.nodeApiService.getNode(id).subscribe(
|
||||
(node) => {
|
||||
@@ -92,6 +94,10 @@ export class FileViewComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
onViewVersion(versionId: string) {
|
||||
this.preview.showResource(this.nodeId, versionId);
|
||||
}
|
||||
|
||||
onViewerVisibilityChanged() {
|
||||
const primaryUrl = this.router.parseUrl(this.router.url).root.children[PRIMARY_OUTLET].toString();
|
||||
this.router.navigateByUrl(primaryUrl);
|
||||
|
@@ -32,7 +32,9 @@
|
||||
[newFileVersion]="newFileVersion"
|
||||
[allowDownload]="allowDownload"
|
||||
[showComments]="showComments"
|
||||
(uploadError)="uploadError($event)"></adf-version-manager>
|
||||
(uploadError)="uploadError($event)"
|
||||
(viewVersion)="onViewVersion($event)"
|
||||
></adf-version-manager>
|
||||
</section>
|
||||
<section mat-dialog-content *ngIf="readOnly">
|
||||
<adf-version-list [node]="contentEntry" [showActions]="false"></adf-version-list>
|
||||
|
@@ -19,6 +19,7 @@ import { Component, Inject, ViewEncapsulation } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { PreviewService } from '../../services/preview.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './version-manager-dialog-adapter.component.html',
|
||||
@@ -34,7 +35,8 @@ export class VersionManagerDialogAdapterComponent {
|
||||
readOnly = false;
|
||||
showVersionComparison = false;
|
||||
|
||||
constructor(@Inject(MAT_DIALOG_DATA) data: any,
|
||||
constructor(private previewService: PreviewService,
|
||||
@Inject(MAT_DIALOG_DATA) data: any,
|
||||
private snackBar: MatSnackBar,
|
||||
private containingDialog?: MatDialogRef<VersionManagerDialogAdapterComponent>) {
|
||||
this.contentEntry = data.contentEntry;
|
||||
@@ -51,6 +53,11 @@ export class VersionManagerDialogAdapterComponent {
|
||||
this.containingDialog.close();
|
||||
}
|
||||
|
||||
onViewVersion(versionId: string) {
|
||||
this.previewService.showResource(this.contentEntry.id, versionId);
|
||||
this.close();
|
||||
}
|
||||
|
||||
hideVersionComparison(isCancelled: boolean | Node) {
|
||||
if (isCancelled) {
|
||||
this.showVersionComparison = false;
|
||||
|
@@ -26,8 +26,12 @@ export class PreviewService {
|
||||
|
||||
constructor(private router: Router) {}
|
||||
|
||||
showResource(resourceId): void {
|
||||
this.router.navigate([{ outlets: { overlay: ['files', resourceId, 'view'] } }]);
|
||||
showResource(resourceId, versionId?): void {
|
||||
if (versionId) {
|
||||
this.router.navigate([{outlets: {overlay: ['files', resourceId, versionId, 'view']}}]);
|
||||
} else {
|
||||
this.router.navigate([{outlets: {overlay: ['files', resourceId, 'view']}}]);
|
||||
}
|
||||
}
|
||||
|
||||
showBlob(name: string, content: Blob): void {
|
||||
|
@@ -22,6 +22,7 @@ Displays the version history of a node in a [Version Manager component](version-
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| allowDownload | `boolean` | true | Enable/disable downloading a version of the current node. |
|
||||
| allowViewVersions | `boolean` | true | Enable/disable viewing a version of the current node. |
|
||||
| node | [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) | | The target node. |
|
||||
| showActions | `boolean` | true | Toggles showing/hiding of version actions |
|
||||
| showComments | `boolean` | true | Toggles showing/hiding of comments |
|
||||
@@ -32,6 +33,7 @@ Displays the version history of a node in a [Version Manager component](version-
|
||||
| ---- | ---- | ----------- |
|
||||
| deleted | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`>` | Emitted when a version is deleted |
|
||||
| restored | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`>` | Emitted when a version is restored |
|
||||
| viewVersion | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | Emitted when viewing a version |
|
||||
|
||||
## Details
|
||||
|
||||
|
@@ -42,6 +42,7 @@ Displays the version history of a node with the ability to upload a new version.
|
||||
| uploadCancel | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<boolean>` | Emitted when an cancelling during upload. |
|
||||
| uploadError | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`>` | Emitted when an error occurs during upload. |
|
||||
| uploadSuccess | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md)`>` | Emitted when a file is uploaded successfully. |
|
||||
| viewVersion | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | Emitted when viewing a version. |
|
||||
|
||||
## Details
|
||||
|
||||
|
@@ -103,6 +103,7 @@ See the [Custom layout](#custom-layout) section for full details of all availabl
|
||||
| thumbnailsTemplate | [`TemplateRef`](https://angular.io/api/core/TemplateRef)`<any>` | null | The template for the pdf thumbnails. |
|
||||
| urlFile | `string` | "" | If you want to load an external file that does not come from ACS you can use this URL to specify where to load the file from. |
|
||||
| urlFileViewer | `string` | null | Viewer to use with the `urlFile` address (`pdf`, `image`, `media`, `text`). Used when `urlFile` has no filename and extension. |
|
||||
| versionId | `string` | null | Version Id of the file to load. |
|
||||
|
||||
### Events
|
||||
|
||||
|
@@ -14,7 +14,8 @@ Allows folders and/or files to be downloaded, with multiple nodes packed as a '.
|
||||
```html
|
||||
<adf-toolbar>
|
||||
<button mat-icon-button
|
||||
[adfNodeDownload]="documentList.selection">
|
||||
[adfNodeDownload]="documentList.selection"
|
||||
[version]="version">
|
||||
<mat-icon>get_app</mat-icon>
|
||||
</button>
|
||||
</adf-toolbar>
|
||||
@@ -31,3 +32,4 @@ Allows folders and/or files to be downloaded, with multiple nodes packed as a '.
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| nodes | [`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md)` \| `[`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md)`[]` | | Nodes to download. |
|
||||
| version | [`VersionEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/VersionEntry.md) | | [Node's](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) version to download. |
|
||||
|
@@ -23,7 +23,8 @@ import {
|
||||
LoginPage,
|
||||
UploadActions,
|
||||
UserModel,
|
||||
UsersActions
|
||||
UsersActions,
|
||||
ViewerPage
|
||||
} from '@alfresco/adf-testing';
|
||||
import { browser, by, element } from 'protractor';
|
||||
import { FileModel } from '../../models/ACS/file.model';
|
||||
@@ -41,6 +42,7 @@ describe('Version component actions', () => {
|
||||
const uploadDialog = new UploadDialogPage();
|
||||
const apiService = new ApiService();
|
||||
const usersActions = new UsersActions(apiService);
|
||||
const viewerPage = new ViewerPage();
|
||||
|
||||
let acsUser: UserModel;
|
||||
|
||||
@@ -151,6 +153,18 @@ describe('Version component actions', () => {
|
||||
await contentServicesPage.checkContentIsDisplayed(txtFileModel.name);
|
||||
});
|
||||
|
||||
it('[C362240] Should be possible to view a previous document version', async () => {
|
||||
await contentServicesPage.versionManagerContent(fileModelVersionTwo.name);
|
||||
await versionManagePage.viewFileVersion('1.0');
|
||||
await viewerPage.expectUrlToContain('1.0');
|
||||
});
|
||||
|
||||
it('[C362241] Should be possible to download a previous document version', async () => {
|
||||
await viewerPage.clickDownloadButton();
|
||||
await FileBrowserUtil.isFileDownloaded(fileModelVersionTwo.name);
|
||||
await viewerPage.clickCloseButton();
|
||||
});
|
||||
|
||||
it('[C307033] Should be possible to cancel the upload of a new version', async () => {
|
||||
await browser.refresh();
|
||||
await contentServicesPage.versionManagerContent(txtFileModel.name);
|
||||
|
@@ -17,7 +17,7 @@
|
||||
|
||||
import * as path from 'path';
|
||||
import { BrowserActions, BrowserVisibility, TogglePage } from '@alfresco/adf-testing';
|
||||
import { browser, by, element } from 'protractor';
|
||||
import { browser, by, element, ElementFinder } from 'protractor';
|
||||
|
||||
export class VersionManagePage {
|
||||
|
||||
@@ -173,6 +173,12 @@ export class VersionManagePage {
|
||||
await BrowserActions.click(restoreButton);
|
||||
}
|
||||
|
||||
async viewFileVersion(version): Promise<void> {
|
||||
await this.clickActionButton(version);
|
||||
const viewButton: ElementFinder = element(by.id(`adf-version-list-action-view-${version}`));
|
||||
await BrowserActions.click(viewButton);
|
||||
}
|
||||
|
||||
async checkActionsArePresent(version: string): Promise<void> {
|
||||
await BrowserVisibility.waitUntilElementIsVisible(element(by.id(`adf-version-list-action-download-${version}`)));
|
||||
await BrowserVisibility.waitUntilElementIsVisible(element(by.id(`adf-version-list-action-delete-${version}`)));
|
||||
|
@@ -16,10 +16,11 @@
|
||||
*/
|
||||
|
||||
import { browser } from 'protractor';
|
||||
import { ApiService, LoginPage, UploadActions, UserModel, UsersActions, ViewerPage } from '@alfresco/adf-testing';
|
||||
import { ApiService, BrowserActions, FileBrowserUtil, LoginPage, UploadActions, UserModel, UsersActions, ViewerPage } from '@alfresco/adf-testing';
|
||||
import { ContentServicesPage } from '../../core/pages/content-services.page';
|
||||
import { FileModel } from '../../models/ACS/file.model';
|
||||
import { NavigationBarPage } from '../../core/pages/navigation-bar.page';
|
||||
import { VersionManagePage } from '../pages/version-manager.page';
|
||||
|
||||
describe('Viewer', () => {
|
||||
|
||||
@@ -32,6 +33,7 @@ describe('Viewer', () => {
|
||||
const uploadActions = new UploadActions(apiService);
|
||||
const usersActions = new UsersActions(apiService);
|
||||
|
||||
const versionManagePage = new VersionManagePage();
|
||||
const acsUser = new UserModel();
|
||||
let txtFileUploaded;
|
||||
|
||||
@@ -40,6 +42,11 @@ describe('Viewer', () => {
|
||||
'location': browser.params.resources.Files.ADF_DOCUMENTS.TXT.file_path
|
||||
});
|
||||
|
||||
const fileModelVersionTwo = new FileModel({
|
||||
'name': browser.params.resources.Files.ADF_DOCUMENTS.TXT.file_name,
|
||||
'location': browser.params.resources.Files.ADF_DOCUMENTS.TXT.file_location
|
||||
});
|
||||
|
||||
beforeAll(async () => {
|
||||
await apiService.getInstance().login(browser.params.testConfig.admin.email, browser.params.testConfig.admin.password);
|
||||
await usersActions.createUser(acsUser);
|
||||
@@ -84,4 +91,22 @@ describe('Viewer', () => {
|
||||
await viewerPage.clickOnTab('Versions');
|
||||
await viewerPage.checkTabIsActive('Versions');
|
||||
});
|
||||
|
||||
it('[C362242] Should the Viewer be able to view a previous version of a file', async () => {
|
||||
await viewerPage.clickCloseButton();
|
||||
await contentServicesPage.versionManagerContent(txtFileInfo.name);
|
||||
await BrowserActions.click(versionManagePage.showNewVersionButton);
|
||||
await versionManagePage.uploadNewVersionFile(fileModelVersionTwo.location);
|
||||
await versionManagePage.closeVersionDialog();
|
||||
await contentServicesPage.doubleClickRow(txtFileUploaded.entry.name);
|
||||
await viewerPage.clickInfoButton();
|
||||
await viewerPage.clickOnTab('Versions');
|
||||
await versionManagePage.viewFileVersion('1.0');
|
||||
await viewerPage.expectUrlToContain('1.0');
|
||||
});
|
||||
|
||||
it('[C362265] Should the Viewer be able to download a previous version of a file', async () => {
|
||||
await viewerPage.clickDownloadButton();
|
||||
await FileBrowserUtil.isFileDownloaded(txtFileInfo.name);
|
||||
});
|
||||
});
|
||||
|
@@ -4,6 +4,7 @@
|
||||
"RESTORE": "Restore",
|
||||
"DELETE": "Delete",
|
||||
"DOWNLOAD": "Download",
|
||||
"VIEW": "View",
|
||||
"UPLOAD": {
|
||||
"TITLE": "Upload new version",
|
||||
"TOOLTIP": "Restriction: you must upload a file with the same name to create a new version of it",
|
||||
|
@@ -12,6 +12,14 @@
|
||||
<div *ngIf="showActions">
|
||||
<mat-menu [id]="'adf-version-list-action-menu-'+version.entry.id"
|
||||
#versionMenu="matMenu" yPosition="below" xPosition="before">
|
||||
<ng-container *adf-acs-version="'7'">
|
||||
<button *ngIf="allowViewVersions"
|
||||
[id]="'adf-version-list-action-view-'+version.entry.id"
|
||||
mat-menu-item
|
||||
(click)="onViewVersion(version.entry.id)">
|
||||
{{ 'ADF_VERSION_LIST.ACTIONS.VIEW' | translate }}
|
||||
</button>
|
||||
</ng-container>
|
||||
<button
|
||||
[id]="'adf-version-list-action-restore-'+version.entry.id"
|
||||
[disabled]="!canUpdate()"
|
||||
|
@@ -228,6 +228,13 @@ describe('VersionListComponent', () => {
|
||||
expect(alfrescoApiService.contentApi.getContentUrl).toHaveBeenCalledWith(nodeId, true);
|
||||
});
|
||||
|
||||
it('should be able to view a version', () => {
|
||||
spyOn(component.viewVersion, 'emit');
|
||||
component.onViewVersion('1.0');
|
||||
fixture.detectChanges();
|
||||
expect(component.viewVersion.emit).toHaveBeenCalledWith('1.0');
|
||||
});
|
||||
|
||||
it('should NOT be able to download a version if configured so', () => {
|
||||
const versionEntry = {
|
||||
entry: {
|
||||
|
@@ -48,6 +48,10 @@ export class VersionListComponent implements OnChanges {
|
||||
@Input()
|
||||
allowDownload = true;
|
||||
|
||||
/** Enable/disable viewing a version of the current node. */
|
||||
@Input()
|
||||
allowViewVersions = true;
|
||||
|
||||
/** Toggles showing/hiding of version actions */
|
||||
@Input()
|
||||
showActions = true;
|
||||
@@ -60,6 +64,10 @@ export class VersionListComponent implements OnChanges {
|
||||
@Output()
|
||||
deleted: EventEmitter<Node> = new EventEmitter<Node>();
|
||||
|
||||
/** Emitted when viewing a version */
|
||||
@Output()
|
||||
viewVersion: EventEmitter<string> = new EventEmitter<string>();
|
||||
|
||||
constructor(private alfrescoApi: AlfrescoApiService,
|
||||
private contentService: ContentService,
|
||||
private dialog: MatDialog) {
|
||||
@@ -92,6 +100,10 @@ export class VersionListComponent implements OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
onViewVersion(versionId) {
|
||||
this.viewVersion.emit(versionId);
|
||||
}
|
||||
|
||||
loadVersionHistory() {
|
||||
this.isLoading = true;
|
||||
this.versionsApi.listVersionHistory(this.node.id).then((versionPaging: VersionPaging) => {
|
||||
|
@@ -38,7 +38,8 @@
|
||||
[allowDownload]="allowDownload"
|
||||
[showComments]="showComments"
|
||||
(deleted)="refresh($event)"
|
||||
(restored)="refresh($event)">
|
||||
(restored)="refresh($event)"
|
||||
(viewVersion)="onViewVersion($event)">
|
||||
</adf-version-list>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -73,6 +73,13 @@ describe('VersionManagerComponent', () => {
|
||||
expect(component.uploadState).toBe('open');
|
||||
});
|
||||
|
||||
it('should be able to view a version', () => {
|
||||
spyOn(component.viewVersion, 'emit');
|
||||
component.onViewVersion('1.0');
|
||||
fixture.detectChanges();
|
||||
expect(component.viewVersion.emit).toHaveBeenCalledWith('1.0');
|
||||
});
|
||||
|
||||
it('should display comments for versions when not configured otherwise', async(() => {
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
|
@@ -75,6 +75,10 @@ export class VersionManagerComponent implements OnInit {
|
||||
@Output()
|
||||
uploadCancel: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||
|
||||
/** Emitted when viewing a version. */
|
||||
@Output()
|
||||
viewVersion: EventEmitter<string> = new EventEmitter<string>();
|
||||
|
||||
@ViewChild('versionList', { static: true })
|
||||
versionListComponent: VersionListComponent;
|
||||
|
||||
@@ -117,6 +121,10 @@ export class VersionManagerComponent implements OnInit {
|
||||
this.uploadCancel.emit(true);
|
||||
}
|
||||
|
||||
onViewVersion(versionId: string) {
|
||||
this.viewVersion.emit(versionId);
|
||||
}
|
||||
|
||||
toggleNewVersion() {
|
||||
this.uploadState = this.uploadState === 'open' ? 'close' : 'open';
|
||||
}
|
||||
|
@@ -26,10 +26,11 @@ import { CoreTestingModule } from '../testing/core.testing.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
template: '<div [adfNodeDownload]="selection"></div>'
|
||||
template: '<div [adfNodeDownload]="selection" [version]="version"></div>'
|
||||
})
|
||||
class TestComponent {
|
||||
selection;
|
||||
version;
|
||||
}
|
||||
|
||||
describe('NodeDownloadDirective', () => {
|
||||
@@ -91,6 +92,22 @@ describe('NodeDownloadDirective', () => {
|
||||
expect(contentService.getContentUrl).toHaveBeenCalledWith(node.entry.id, true);
|
||||
});
|
||||
|
||||
it('should download selected node version as file', () => {
|
||||
component.version = {
|
||||
entry: {
|
||||
id: '1.0'
|
||||
}
|
||||
};
|
||||
spyOn(contentService, 'getVersionContentUrl');
|
||||
const node = {entry: {id: 'node-id', isFile: true}};
|
||||
component.selection = [node];
|
||||
|
||||
fixture.detectChanges();
|
||||
element.triggerEventHandler('click', null);
|
||||
|
||||
expect(contentService.getVersionContentUrl).toHaveBeenCalledWith(node.entry.id, '1.0', true);
|
||||
});
|
||||
|
||||
it('should download selected shared node as file', () => {
|
||||
spyOn(contentService, 'getContentUrl');
|
||||
const node = { entry: { nodeId: 'shared-node-id', isFile: true } };
|
||||
|
@@ -19,7 +19,7 @@ import { Directive, Input, HostListener } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { AlfrescoApiService } from '../services/alfresco-api.service';
|
||||
import { DownloadZipDialogComponent } from '../dialogs/download-zip/download-zip.dialog';
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
import { NodeEntry, VersionEntry } from '@alfresco/js-api';
|
||||
import { DownloadService } from '../services/download.service';
|
||||
|
||||
/**
|
||||
@@ -35,6 +35,10 @@ export class NodeDownloadDirective {
|
||||
@Input('adfNodeDownload')
|
||||
nodes: NodeEntry | NodeEntry[];
|
||||
|
||||
/** Node's version to download. */
|
||||
@Input()
|
||||
version: VersionEntry;
|
||||
|
||||
@HostListener('click')
|
||||
onClick() {
|
||||
this.downloadNodes(this.nodes);
|
||||
@@ -101,8 +105,14 @@ export class NodeDownloadDirective {
|
||||
// nodeId for Shared node
|
||||
const id = (<any> node.entry).nodeId || node.entry.id;
|
||||
|
||||
const url = contentApi.getContentUrl(id, true);
|
||||
const fileName = node.entry.name;
|
||||
let url, fileName;
|
||||
if (this.version) {
|
||||
url = contentApi.getVersionContentUrl(id, this.version.entry.id, true);
|
||||
fileName = this.version.entry.name;
|
||||
} else {
|
||||
url = contentApi.getContentUrl(id, true);
|
||||
fileName = node.entry.name;
|
||||
}
|
||||
|
||||
this.downloadService.downloadUrl(url, fileName);
|
||||
}
|
||||
|
@@ -82,7 +82,8 @@
|
||||
[attr.aria-label]="'ADF_VIEWER.ACTIONS.DOWNLOAD' | translate"
|
||||
title="{{ 'ADF_VIEWER.ACTIONS.DOWNLOAD' | translate }}"
|
||||
data-automation-id="adf-toolbar-download"
|
||||
[adfNodeDownload]="nodeEntry">
|
||||
[adfNodeDownload]="nodeEntry"
|
||||
[version]="versionEntry">
|
||||
<mat-icon>file_download</mat-icon>
|
||||
</button>
|
||||
|
||||
|
@@ -20,7 +20,7 @@ import {
|
||||
Input, OnChanges, Output, TemplateRef,
|
||||
ViewEncapsulation, OnInit, OnDestroy
|
||||
} from '@angular/core';
|
||||
import { RenditionPaging, SharedLinkEntry, Node, RenditionEntry, NodeEntry } from '@alfresco/js-api';
|
||||
import { SharedLinkEntry, Node, Version, RenditionEntry, NodeEntry, VersionEntry } from '@alfresco/js-api';
|
||||
import { BaseEvent } from '../../events';
|
||||
import { AlfrescoApiService } from '../../services/alfresco-api.service';
|
||||
import { LogService } from '../../services/log.service';
|
||||
@@ -74,6 +74,10 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
@Input()
|
||||
nodeId: string = null;
|
||||
|
||||
/** Version Id of the file to load. */
|
||||
@Input()
|
||||
versionId: string = null;
|
||||
|
||||
/** Shared link id (to display shared file). */
|
||||
@Input()
|
||||
sharedLinkId: string = null;
|
||||
@@ -206,6 +210,7 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
viewerType = 'unknown';
|
||||
isLoading = false;
|
||||
nodeEntry: NodeEntry;
|
||||
versionEntry: VersionEntry;
|
||||
|
||||
extensionTemplates: { template: TemplateRef<any>, isVisible: boolean }[] = [];
|
||||
externalExtensions: string[] = [];
|
||||
@@ -255,6 +260,17 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
).subscribe((node) => this.onNodeUpdated(node))
|
||||
);
|
||||
|
||||
this.subscriptions.push(
|
||||
this.viewUtils.viewerTypeChange.subscribe((type: string) => {
|
||||
this.viewerType = type;
|
||||
})
|
||||
);
|
||||
this.subscriptions.push(
|
||||
this.viewUtils.urlFileContentChange.subscribe((content: string) => {
|
||||
this.urlFileContent = content;
|
||||
})
|
||||
);
|
||||
|
||||
this.loadExtensions();
|
||||
}
|
||||
|
||||
@@ -298,9 +314,20 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
this.apiService.nodesApi.getNode(this.nodeId, { include: ['allowableOperations'] }).then(
|
||||
(node: NodeEntry) => {
|
||||
this.nodeEntry = node;
|
||||
this.setUpNodeFile(node.entry).then(() => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
if (this.versionId) {
|
||||
this.apiService.versionsApi.getVersion(this.nodeId, this.versionId).then(
|
||||
(version: VersionEntry) => {
|
||||
this.versionEntry = version;
|
||||
this.setUpNodeFile(node.entry, version.entry).then(() => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.setUpNodeFile(node.entry).then(() => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
() => {
|
||||
this.isLoading = false;
|
||||
@@ -353,21 +380,23 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
this.scrollTop();
|
||||
}
|
||||
|
||||
private async setUpNodeFile(data: Node) {
|
||||
private async setUpNodeFile(nodeData: Node, versionData?: Version) {
|
||||
let setupNode;
|
||||
|
||||
if (data.content) {
|
||||
this.mimeType = data.content.mimeType;
|
||||
if (versionData && versionData.content) {
|
||||
this.mimeType = versionData.content.mimeType;
|
||||
} else if (nodeData.content) {
|
||||
this.mimeType = nodeData.content.mimeType;
|
||||
}
|
||||
|
||||
this.fileTitle = this.getDisplayName(data.name);
|
||||
this.fileTitle = this.getDisplayName(nodeData.name);
|
||||
|
||||
this.urlFileContent = this.apiService.contentApi.getContentUrl(data.id);
|
||||
this.urlFileContent = versionData ? this.apiService.contentApi.getVersionContentUrl(this.nodeId, versionData.id) :
|
||||
this.urlFileContent = this.cacheBusterNumber ? this.urlFileContent + '&' + this.cacheBusterNumber : this.urlFileContent;
|
||||
|
||||
this.extension = this.getFileExtension(data.name);
|
||||
this.extension = this.getFileExtension(versionData ? versionData.name : nodeData.name);
|
||||
|
||||
this.fileName = data.name;
|
||||
this.fileName = versionData ? versionData.name : nodeData.name;
|
||||
|
||||
this.viewerType = this.getViewerTypeByExtension(this.extension);
|
||||
if (this.viewerType === 'unknown') {
|
||||
@@ -375,12 +404,12 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
if (this.viewerType === 'unknown') {
|
||||
setupNode = this.displayNodeRendition(data.id);
|
||||
setupNode = this.viewUtils.displayNodeRendition(nodeData.id, versionData ? versionData.id : undefined);
|
||||
}
|
||||
|
||||
this.extensionChange.emit(this.extension);
|
||||
this.sidebarRightTemplateContext.node = data;
|
||||
this.sidebarLeftTemplateContext.node = data;
|
||||
this.sidebarRightTemplateContext.node = nodeData;
|
||||
this.sidebarLeftTemplateContext.node = nodeData;
|
||||
this.scrollTop();
|
||||
|
||||
return setupNode;
|
||||
@@ -603,25 +632,6 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
private async displayNodeRendition(nodeId: string) {
|
||||
try {
|
||||
const rendition = await this.resolveRendition(nodeId, 'pdf');
|
||||
if (rendition) {
|
||||
const renditionId = rendition.entry.id;
|
||||
|
||||
if (renditionId === 'pdf') {
|
||||
this.viewerType = 'pdf';
|
||||
} else if (renditionId === 'imgpreview') {
|
||||
this.viewerType = 'image';
|
||||
}
|
||||
|
||||
this.urlFileContent = this.apiService.contentApi.getRenditionUrl(nodeId, renditionId);
|
||||
}
|
||||
} catch (err) {
|
||||
this.logService.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
private async displaySharedLinkRendition(sharedId: string) {
|
||||
try {
|
||||
const rendition: RenditionEntry = await this.apiService.renditionsApi.getSharedLinkRendition(sharedId, 'pdf');
|
||||
@@ -643,69 +653,6 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
private async resolveRendition(nodeId: string, renditionId: string): Promise<RenditionEntry> {
|
||||
renditionId = renditionId.toLowerCase();
|
||||
|
||||
const supportedRendition: RenditionPaging = await this.apiService.renditionsApi.getRenditions(nodeId);
|
||||
|
||||
let rendition: RenditionEntry = supportedRendition.list.entries.find((renditionEntry: RenditionEntry) => renditionEntry.entry.id.toLowerCase() === renditionId);
|
||||
if (!rendition) {
|
||||
renditionId = 'imgpreview';
|
||||
rendition = supportedRendition.list.entries.find((renditionEntry: RenditionEntry) => renditionEntry.entry.id.toLowerCase() === renditionId);
|
||||
}
|
||||
|
||||
if (rendition) {
|
||||
const status: string = rendition.entry.status.toString();
|
||||
|
||||
if (status === 'NOT_CREATED') {
|
||||
try {
|
||||
await this.apiService.renditionsApi.createRendition(nodeId, { id: renditionId }).then(() => {
|
||||
this.viewerType = 'in_creation';
|
||||
});
|
||||
rendition = await this.waitRendition(nodeId, renditionId);
|
||||
} catch (err) {
|
||||
this.logService.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rendition;
|
||||
}
|
||||
|
||||
private async waitRendition(nodeId: string, renditionId: string): Promise<RenditionEntry> {
|
||||
let currentRetry: number = 0;
|
||||
return new Promise<RenditionEntry>((resolve, reject) => {
|
||||
const intervalId = setInterval(() => {
|
||||
currentRetry++;
|
||||
if (this.maxRetries >= currentRetry) {
|
||||
this.apiService.renditionsApi.getRendition(nodeId, renditionId).then((rendition: RenditionEntry) => {
|
||||
const status: string = rendition.entry.status.toString();
|
||||
if (status === 'CREATED') {
|
||||
|
||||
if (renditionId === 'pdf') {
|
||||
this.viewerType = 'pdf';
|
||||
} else if (renditionId === 'imgpreview') {
|
||||
this.viewerType = 'image';
|
||||
}
|
||||
|
||||
this.urlFileContent = this.apiService.contentApi.getRenditionUrl(nodeId, renditionId);
|
||||
|
||||
clearInterval(intervalId);
|
||||
return resolve(rendition);
|
||||
}
|
||||
}, () => {
|
||||
this.viewerType = 'error_in_creation';
|
||||
return reject();
|
||||
});
|
||||
} else {
|
||||
this.isLoading = false;
|
||||
this.viewerType = 'error_in_creation';
|
||||
clearInterval(intervalId);
|
||||
}
|
||||
}, this.TRY_TIMEOUT);
|
||||
});
|
||||
}
|
||||
|
||||
checkExtensions(extensionAllowed) {
|
||||
if (typeof extensionAllowed === 'string') {
|
||||
return this.extension.toLowerCase() === extensionAllowed.toLowerCase();
|
||||
|
@@ -19,6 +19,7 @@ import { Injectable } from '@angular/core';
|
||||
import { RenditionEntry, RenditionPaging } from '@alfresco/js-api';
|
||||
import { AlfrescoApiService } from '../../services/alfresco-api.service';
|
||||
import { LogService } from '../../services/log.service';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -54,6 +55,17 @@ export class ViewUtilService {
|
||||
media: ['video/mp4', 'video/webm', 'video/ogg', 'audio/mpeg', 'audio/ogg', 'audio/wav']
|
||||
};
|
||||
|
||||
/**
|
||||
* Timeout used for setInterval.
|
||||
*/
|
||||
TRY_TIMEOUT: number = 10000;
|
||||
|
||||
/**
|
||||
* Subscribers needed for ViewerComponent to update the viewerType and urlFileContent.
|
||||
*/
|
||||
viewerTypeChange: Subject<string> = new Subject<string>();
|
||||
urlFileContentChange: Subject<string> = new Subject<string>();
|
||||
|
||||
constructor(private apiService: AlfrescoApiService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
@@ -167,4 +179,110 @@ export class ViewUtilService {
|
||||
return new Promise<RenditionEntry>((resolve) => resolve(rendition));
|
||||
}
|
||||
|
||||
async displayNodeRendition(nodeId: string, versionId?: string) {
|
||||
try {
|
||||
const rendition = await this.resolveNodeRendition(nodeId, 'pdf', versionId);
|
||||
if (rendition) {
|
||||
const renditionId = rendition.entry.id;
|
||||
|
||||
if (renditionId === 'pdf') {
|
||||
this.viewerTypeChange.next('pdf');
|
||||
} else if (renditionId === 'imgpreview') {
|
||||
this.viewerTypeChange.next('image');
|
||||
}
|
||||
|
||||
const urlFileContent = versionId ? this.apiService.contentApi.getVersionRenditionUrl(nodeId, versionId, renditionId) :
|
||||
this.apiService.contentApi.getRenditionUrl(nodeId, renditionId);
|
||||
this.urlFileContentChange.next(urlFileContent);
|
||||
}
|
||||
} catch (err) {
|
||||
this.logService.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
private async resolveNodeRendition(nodeId: string, renditionId: string, versionId?: string): Promise<RenditionEntry> {
|
||||
renditionId = renditionId.toLowerCase();
|
||||
|
||||
const supportedRendition: RenditionPaging = versionId ? await this.apiService.versionsApi.listVersionRenditions(nodeId, versionId) :
|
||||
await this.apiService.renditionsApi.getRenditions(nodeId);
|
||||
|
||||
let rendition: RenditionEntry = supportedRendition.list.entries.find((renditionEntry: RenditionEntry) => renditionEntry.entry.id.toLowerCase() === renditionId);
|
||||
if (!rendition) {
|
||||
renditionId = 'imgpreview';
|
||||
rendition = supportedRendition.list.entries.find((renditionEntry: RenditionEntry) => renditionEntry.entry.id.toLowerCase() === renditionId);
|
||||
}
|
||||
|
||||
if (rendition) {
|
||||
const status: string = rendition.entry.status.toString();
|
||||
|
||||
if (status === 'NOT_CREATED') {
|
||||
try {
|
||||
if (versionId) {
|
||||
await this.apiService.versionsApi.createVersionRendition(nodeId, versionId, {id: renditionId}).then(() => {
|
||||
this.viewerTypeChange.next('in_creation');
|
||||
});
|
||||
} else {
|
||||
await this.apiService.renditionsApi.createRendition(nodeId, {id: renditionId}).then(() => {
|
||||
this.viewerTypeChange.next('in_creation');
|
||||
});
|
||||
}
|
||||
rendition = await this.waitNodeRendition(nodeId, renditionId, versionId);
|
||||
} catch (err) {
|
||||
this.logService.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rendition;
|
||||
}
|
||||
|
||||
private async waitNodeRendition(nodeId: string, renditionId: string, versionId?: string): Promise<RenditionEntry> {
|
||||
let currentRetry: number = 0;
|
||||
return new Promise<RenditionEntry>((resolve, reject) => {
|
||||
const intervalId = setInterval(() => {
|
||||
currentRetry++;
|
||||
if (this.maxRetries >= currentRetry) {
|
||||
if (!versionId) {
|
||||
this.apiService.versionsApi.getVersionRendition(nodeId, versionId, renditionId).then((rendition: RenditionEntry) => {
|
||||
this.handleNodeRendition(rendition, nodeId, renditionId, versionId);
|
||||
clearInterval(intervalId);
|
||||
return resolve(rendition);
|
||||
}, () => {
|
||||
this.viewerTypeChange.next('error_in_creation');
|
||||
return reject();
|
||||
});
|
||||
} else {
|
||||
this.apiService.renditionsApi.getRendition(nodeId, renditionId).then((rendition: RenditionEntry) => {
|
||||
this.handleNodeRendition(rendition, nodeId, renditionId);
|
||||
clearInterval(intervalId);
|
||||
return resolve(rendition);
|
||||
}, () => {
|
||||
this.viewerTypeChange.next('error_in_creation');
|
||||
return reject();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.viewerTypeChange.next('error_in_creation');
|
||||
clearInterval(intervalId);
|
||||
}
|
||||
}, this.TRY_TIMEOUT);
|
||||
});
|
||||
}
|
||||
|
||||
private async handleNodeRendition(rendition: RenditionEntry, nodeId: string, renditionId: string, versionId?: string) {
|
||||
const status: string = rendition.entry.status.toString();
|
||||
if (status === 'CREATED') {
|
||||
|
||||
if (renditionId === 'pdf') {
|
||||
this.viewerTypeChange.next('pdf');
|
||||
} else if (renditionId === 'imgpreview') {
|
||||
this.viewerTypeChange.next('image');
|
||||
}
|
||||
|
||||
const urlFileContent = versionId ? this.apiService.contentApi.getVersionRenditionUrl(nodeId, versionId, renditionId) :
|
||||
this.apiService.contentApi.getRenditionUrl(nodeId, renditionId);
|
||||
this.urlFileContentChange.next(urlFileContent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -637,4 +637,8 @@ export class ViewerPage {
|
||||
const unknownFormatLabel = this.unknownFormat.element(by.css(`.adf-viewer__unknown-label`));
|
||||
return BrowserActions.getText(unknownFormatLabel);
|
||||
}
|
||||
|
||||
async expectUrlToContain(text: string): Promise<void> {
|
||||
await expect(browser.getCurrentUrl()).toContain(text);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user