mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-3443] basic printing support (#3777)
* printing service * code fixes * update code
This commit is contained in:
committed by
Eugenio Romano
parent
3857364b39
commit
c5c1aa9ecb
@@ -98,7 +98,11 @@
|
|||||||
</adf-info-drawer>
|
</adf-info-drawer>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<adf-viewer [nodeId]="nodeId" [allowSidebar]="true" [sidebarTemplate]="sidebarTemplate">
|
<adf-viewer
|
||||||
|
[nodeId]="nodeId"
|
||||||
|
[allowPrint]="true"
|
||||||
|
[allowSidebar]="true"
|
||||||
|
[sidebarTemplate]="sidebarTemplate">
|
||||||
|
|
||||||
<adf-viewer-toolbar-actions>
|
<adf-viewer-toolbar-actions>
|
||||||
<button mat-icon-button>
|
<button mat-icon-button>
|
||||||
|
@@ -95,6 +95,7 @@ import { ProcessContentService } from './form/services/process-content.service';
|
|||||||
import { WidgetVisibilityService } from './form/services/widget-visibility.service';
|
import { WidgetVisibilityService } from './form/services/widget-visibility.service';
|
||||||
import { EcmUserService } from './userinfo/services/ecm-user.service';
|
import { EcmUserService } from './userinfo/services/ecm-user.service';
|
||||||
import { BpmUserService } from './userinfo/services/bpm-user.service';
|
import { BpmUserService } from './userinfo/services/bpm-user.service';
|
||||||
|
import { ViewUtilService } from './viewer/services/view-util.service';
|
||||||
|
|
||||||
export function createTranslateLoader(http: HttpClient, logService: LogService) {
|
export function createTranslateLoader(http: HttpClient, logService: LogService) {
|
||||||
return new TranslateLoaderService(http, logService);
|
return new TranslateLoaderService(http, logService);
|
||||||
@@ -148,7 +149,8 @@ export function providers() {
|
|||||||
ProcessContentService,
|
ProcessContentService,
|
||||||
WidgetVisibilityService,
|
WidgetVisibilityService,
|
||||||
EcmUserService,
|
EcmUserService,
|
||||||
BpmUserService
|
BpmUserService,
|
||||||
|
ViewUtilService
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,6 +30,7 @@ import { ViewerOpenWithComponent } from './viewer-open-with.component';
|
|||||||
import { ViewerSidebarComponent } from './viewer-sidebar.component';
|
import { ViewerSidebarComponent } from './viewer-sidebar.component';
|
||||||
import { ViewerToolbarComponent } from './viewer-toolbar.component';
|
import { ViewerToolbarComponent } from './viewer-toolbar.component';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
import { ViewUtilService } from '../services/view-util.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-viewer',
|
selector: 'adf-viewer',
|
||||||
@@ -245,6 +246,7 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
|
|||||||
};
|
};
|
||||||
|
|
||||||
constructor(private apiService: AlfrescoApiService,
|
constructor(private apiService: AlfrescoApiService,
|
||||||
|
private viewUtils: ViewUtilService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private location: Location,
|
private location: Location,
|
||||||
private el: ElementRef) {
|
private el: ElementRef) {
|
||||||
@@ -588,6 +590,10 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
|
|||||||
if (this.allowPrint) {
|
if (this.allowPrint) {
|
||||||
const args = new BaseEvent();
|
const args = new BaseEvent();
|
||||||
this.print.next(args);
|
this.print.next(args);
|
||||||
|
|
||||||
|
if (!args.defaultPrevented) {
|
||||||
|
this.viewUtils.printFileGeneric(this.nodeId, this.mimeType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export * from './services/view-util.service';
|
||||||
export * from './components/viewer.component';
|
export * from './components/viewer.component';
|
||||||
export * from './components/imgViewer.component';
|
export * from './components/imgViewer.component';
|
||||||
export * from './components/mediaPlayer.component';
|
export * from './components/mediaPlayer.component';
|
||||||
|
168
lib/core/viewer/services/view-util.service.ts
Normal file
168
lib/core/viewer/services/view-util.service.ts
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { RenditionEntry } from 'alfresco-js-api';
|
||||||
|
import { AlfrescoApiService } from '../../services/alfresco-api.service';
|
||||||
|
import { LogService } from '../../services/log.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ViewUtilService {
|
||||||
|
static TARGET = '_new';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content groups based on categorization of files that can be viewed in the web browser. This
|
||||||
|
* implementation or grouping is tied to the definition the ng component: ViewerComponent
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:variable-name
|
||||||
|
static ContentGroup = {
|
||||||
|
IMAGE: 'image',
|
||||||
|
MEDIA: 'media',
|
||||||
|
PDF: 'pdf',
|
||||||
|
TEXT: 'text'
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Based on ViewerComponent Implementation, this value is used to determine how many times we try
|
||||||
|
* to get the rendition of a file for preview, or printing.
|
||||||
|
*/
|
||||||
|
maxRetries = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mime-type grouping based on the ViewerComponent.
|
||||||
|
*/
|
||||||
|
private mimeTypes = {
|
||||||
|
text: ['text/plain', 'text/csv', 'text/xml', 'text/html', 'application/x-javascript'],
|
||||||
|
pdf: ['application/pdf'],
|
||||||
|
image: ['image/png', 'image/jpeg', 'image/gif', 'image/bmp', 'image/svg+xml'],
|
||||||
|
media: ['video/mp4', 'video/webm', 'video/ogg', 'audio/mpeg', 'audio/ogg', 'audio/wav']
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(private apiService: AlfrescoApiService,
|
||||||
|
private logService: LogService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method takes a url to trigger the print dialog against, and the type of artifact that it
|
||||||
|
* is.
|
||||||
|
* This URL should be one that can be rendered in the browser, for example PDF, Image, or Text
|
||||||
|
*/
|
||||||
|
printFile(url: string, type: string): void {
|
||||||
|
const pwa = window.open(url, ViewUtilService.TARGET);
|
||||||
|
if (pwa) {
|
||||||
|
// Because of the way chrome focus and close image window vs. pdf preview window
|
||||||
|
if (type === ViewUtilService.ContentGroup.IMAGE) {
|
||||||
|
pwa.onfocus = () => {
|
||||||
|
setTimeout( () => {
|
||||||
|
pwa.close();
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pwa.onload = () => {
|
||||||
|
pwa.print();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch the File Print dialog from anywhere other than the preview service, which resolves the
|
||||||
|
* rendition of the object that can be printed from a web browser.
|
||||||
|
* These are: images, PDF files, or PDF rendition of files.
|
||||||
|
* We also force PDF rendition for TEXT type objects, otherwise the default URL is to download.
|
||||||
|
* TODO there are different TEXT type objects, (HTML, plaintext, xml, etc. we should determine how these are handled)
|
||||||
|
*/
|
||||||
|
printFileGeneric(objectId: string, mimeType: string): void {
|
||||||
|
const nodeId = objectId;
|
||||||
|
const type: string = this.getViewerTypeByMimeType(mimeType);
|
||||||
|
|
||||||
|
this.getRendition(nodeId, ViewUtilService.ContentGroup.PDF)
|
||||||
|
.then(value => {
|
||||||
|
const url: string = this.getRenditionUrl(nodeId, type, (value ? true : false));
|
||||||
|
const printType = (type === ViewUtilService.ContentGroup.PDF
|
||||||
|
|| type === ViewUtilService.ContentGroup.TEXT)
|
||||||
|
? ViewUtilService.ContentGroup.PDF : type;
|
||||||
|
this.printFile(url, printType);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
this.logService.error('Error with Printing');
|
||||||
|
this.logService.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getRenditionUrl(nodeId: string, type: string, renditionExists: boolean): string {
|
||||||
|
return (renditionExists && type !== ViewUtilService.ContentGroup.IMAGE) ?
|
||||||
|
this.apiService.contentApi.getRenditionUrl(nodeId, ViewUtilService.ContentGroup.PDF) :
|
||||||
|
this.apiService.contentApi.getContentUrl(nodeId, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async waitRendition(nodeId: string, renditionId: string, retries: number): Promise<RenditionEntry> {
|
||||||
|
const rendition = await this.apiService.renditionsApi.getRendition(nodeId, renditionId);
|
||||||
|
|
||||||
|
if (this.maxRetries < retries) {
|
||||||
|
const status = rendition.entry.status.toString();
|
||||||
|
|
||||||
|
if (status === 'CREATED') {
|
||||||
|
return rendition;
|
||||||
|
} else {
|
||||||
|
retries += 1;
|
||||||
|
await this.wait(1000);
|
||||||
|
return await this.waitRendition(nodeId, renditionId, retries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getViewerTypeByMimeType(mimeType: string): string {
|
||||||
|
if (mimeType) {
|
||||||
|
mimeType = mimeType.toLowerCase();
|
||||||
|
|
||||||
|
const editorTypes = Object.keys(this.mimeTypes);
|
||||||
|
for (const type of editorTypes) {
|
||||||
|
if (this.mimeTypes[type].indexOf(mimeType) >= 0) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
wait(ms: number): Promise<any> {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRendition(nodeId: string, renditionId: string): Promise<RenditionEntry> {
|
||||||
|
const supported = await this.apiService.renditionsApi.getRenditions(nodeId);
|
||||||
|
let rendition = supported.list.entries.find(obj => obj.entry.id.toLowerCase() === renditionId);
|
||||||
|
|
||||||
|
if (rendition) {
|
||||||
|
const status = rendition.entry.status.toString();
|
||||||
|
|
||||||
|
if (status === 'NOT_CREATED') {
|
||||||
|
try {
|
||||||
|
await this.apiService.renditionsApi.createRendition(nodeId, {id: renditionId});
|
||||||
|
rendition = await this.waitRendition(nodeId, renditionId, 0);
|
||||||
|
} catch (err) {
|
||||||
|
this.logService.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Promise(resolve => resolve(rendition));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user