Denys Vuika 6f968f7e4a
[AAE-5637] Remove SCSS mixins and use CSS variables (#7250)
* remove default-class mixin and use regular import

* cleanup colors

* remove variables file, fix bugs in animations

* proper ordering of imports, core css vars

* cleanup snackbar and material themes

* tags component

* login component styles

* app login

* toolbar component styles

* breadcrumb styles

* dropdown breadcrumb

* app layout component

* demo shell: files component

* aspect list styles

* content metadata styles

* node selector

* name location cell

* node share dialog

* content type dialog

* folder dialog

* document list

* datatable theme

* pagination theme

* viewer theme

* viewer theme

* user-info theme

* container widget

* dynamic table theme

* form widgets

* form theme

* form renderer

* sidebar menu

* header theme

* info drawer theme

* comment list

* commens and layout container

* sidenav layout

* empty content

* error content

* clipboard theme

* search input

* tooltip card and notification history

* card view theme

* remove unused keys

* add permission dialog

* search and permission dialogs

* version comparison and column themes

* upload drag area and cleanup references

* remove the need for content styles

* insight components

* cleanup insights theme

* process components

* process components

* process cloud themes

* cleanup unsed imports

* cleanup mixins

* update build scripts

* test fixes

* remove fdescribe

* css fixes

* update unit tests
2021-09-29 13:17:05 +01:00

212 lines
5.6 KiB
TypeScript

/*!
* @license
* Copyright 2019 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 {
Component,
Input,
OnChanges,
SimpleChanges,
ViewEncapsulation,
ElementRef,
Output,
EventEmitter, AfterViewInit, ViewChild, HostListener
} from '@angular/core';
import { ContentService } from '../../services/content.service';
import { AppConfigService } from './../../app-config/app-config.service';
import Cropper from 'cropperjs';
@Component({
selector: 'adf-img-viewer',
templateUrl: './img-viewer.component.html',
styleUrls: ['./img-viewer.component.scss'],
host: { 'class': 'adf-image-viewer' },
encapsulation: ViewEncapsulation.None
})
export class ImgViewerComponent implements AfterViewInit, OnChanges {
@Input()
showToolbar = true;
@Input()
readOnly = true;
@Input()
urlFile: string;
@Input()
blobFile: Blob;
@Input()
nameFile: string;
@Output()
error = new EventEmitter<any>();
@Output()
submit = new EventEmitter<any>();
@ViewChild('image', { static: false})
public imageElement: ElementRef;
public scale: number = 1.0;
public cropper: Cropper;
public isEditing: boolean = false;
get currentScaleText(): string {
return Math.round(this.scale * 100) + '%';
}
constructor(
private appConfigService: AppConfigService,
private contentService: ContentService) {
this.initializeScaling();
}
initializeScaling() {
const scaling = this.appConfigService.get<number>('adf-viewer.image-viewer-scaling', undefined) / 100;
if (scaling) {
this.scale = scaling;
}
}
ngAfterViewInit() {
this.cropper = new Cropper(this.imageElement.nativeElement, {
autoCrop: false,
dragMode: 'move',
background: false,
scalable: true,
zoomOnWheel: false,
toggleDragModeOnDblclick: false,
viewMode: 1,
checkCrossOrigin: false,
ready: () => {
this.updateCanvasContainer();
}
});
}
ngOnDestroy() {
this.cropper.destroy();
}
@HostListener('document:keydown', ['$event'])
onKeyDown(event: KeyboardEvent) {
switch (event.key) {
case 'ArrowLeft':
event.preventDefault();
this.cropper.move(-3, 0);
break;
case 'ArrowUp':
event.preventDefault();
this.cropper.move(0, -3);
break;
case 'ArrowRight':
event.preventDefault();
this.cropper.move(3, 0);
break;
case 'ArrowDown':
event.preventDefault();
this.cropper.move(0, 3);
break;
case 'i':
this.zoomIn();
break;
case 'o':
this.zoomOut();
break;
case 'r':
this.rotateImage();
break;
default:
}
}
ngOnChanges(changes: SimpleChanges) {
const blobFile = changes['blobFile'];
if (blobFile && blobFile.currentValue) {
this.urlFile = this.contentService.createTrustedUrl(this.blobFile);
return;
}
if (!this.urlFile && !this.blobFile) {
throw new Error('Attribute urlFile or blobFile is required');
}
}
zoomIn() {
this.cropper.zoom( 0.2);
this.scale = +((this.scale + 0.2).toFixed(1));
}
zoomOut() {
if (this.scale > 0.2) {
this.cropper.zoom( -0.2 );
this.scale = +((this.scale - 0.2).toFixed(1));
}
}
rotateImage() {
this.isEditing = true;
this.cropper.rotate( -90);
}
cropImage() {
this.isEditing = true;
this.cropper.setDragMode('crop');
this.cropper.crop();
}
save() {
this.isEditing = false;
this.cropper.setDragMode('move');
this.cropper.getCroppedCanvas().toBlob((blob) => {
this.submit.emit(blob);
this.cropper.replace(this.cropper.getCroppedCanvas().toDataURL());
this.cropper.clear();
});
}
reset() {
this.isEditing = false;
this.cropper.clear();
this.cropper.reset();
this.cropper.setDragMode('move');
this.scale = 1.0;
this.updateCanvasContainer();
}
updateCanvasContainer() {
if (this.imageElement.nativeElement.width < this.cropper.getContainerData().width) {
const width = this.imageElement.nativeElement.width;
const height = this.imageElement.nativeElement.height;
const top = (this.cropper.getContainerData().height - this.imageElement.nativeElement.height) / 2;
const left = (this.cropper.getContainerData().width - this.imageElement.nativeElement.width) / 2;
this.cropper.setCanvasData({
width,
height,
top,
left
});
}
}
onImageError() {
this.error.emit();
}
}