File
Implements
Metadata
exportAs |
lib-upload-file |
selector |
lib-upload-file |
styleUrls |
./upload-file.component.scss |
templateUrl |
./upload-file.component.html |
Index
Properties
|
|
Methods
|
|
Inputs
|
|
Outputs
|
|
Constructor
constructor(_document: any, _snackBarService: SnackBarService, _dialog: MatDialog)
|
|
Parameters :
Name |
Type |
Optional |
_document |
any
|
No
|
_snackBarService |
SnackBarService
|
No
|
_dialog |
MatDialog
|
No
|
|
content
|
Type : TemplateRef<any>
|
|
fileType
|
Type : "image" | "image360" | "document"
|
|
Outputs
loadImage
|
Type : EventEmitter<UserMedia | []>
|
|
Methods
Private
createDocuments
|
createDocuments(files: any[])
|
|
Parameters :
Name |
Type |
Optional |
files |
any[]
|
No
|
|
Private
createImages360
|
createImages360(files: any[])
|
|
Parameters :
Name |
Type |
Optional |
files |
any[]
|
No
|
|
Public
onChangeFile
|
onChangeFile(event)
|
|
|
Public
onDeletePhoto
|
onDeletePhoto()
|
|
|
Private
openCropper
|
openCropper(files: any[])
|
|
Parameters :
Name |
Type |
Optional |
files |
any[]
|
No
|
|
Private
Static
validateDocuments
|
validateDocuments(files: FileList)
|
|
Parameters :
Name |
Type |
Optional |
files |
FileList
|
No
|
Returns : any[]
|
Private
Static
validateImages
|
validateImages(files: FileList)
|
|
Parameters :
Name |
Type |
Optional |
files |
FileList
|
No
|
Returns : any[]
|
Public
_document
|
Type : any
|
Decorators :
@Inject(DOCUMENT)
|
|
import {Component, ContentChild, EventEmitter, Inject, Input, OnInit, Optional, Output, TemplateRef} from '@angular/core';
import {MatDialog} from '@angular/material/dialog';
import {DOCUMENT} from '@angular/common';
import {CropImageComponent} from '../crop-image/crop-image.component';
import {PFileTypeEnum, UserMedia} from '@maplander/types';
import {Utils} from '../../../utils/utils';
import {SnackBarService} from '@maplander/core';
import {DataCropImage} from '../../../utils/models/data-crop-image';
@Component({
exportAs: 'lib-upload-file',
selector: 'lib-upload-file',
templateUrl: './upload-file.component.html',
styleUrls: ['./upload-file.component.scss']
})
export class UploadFileComponent implements OnInit {
@ContentChild(TemplateRef, {static: true})
@Input() content: TemplateRef<any>;
@Input() fab: boolean;
@Input() multiple: boolean;
@Input() circle: boolean;
@Input() fileType: 'image' | 'image360' | 'document';
@Input() disabled: boolean;
@Input() aspectRatio: number;
@Input() isLoaded: boolean;
@Output() loadImage: EventEmitter<UserMedia | UserMedia[]>;
public id: string;
public accept: string;
constructor(
@Inject(DOCUMENT) public _document: any,
@Optional() private _snackBarService: SnackBarService,
private _dialog: MatDialog
) {
this.id = Utils.randomString();
this.loadImage = new EventEmitter<UserMedia | UserMedia[]>();
this.accept = 'image/jpg, image/jpeg, image/png';
}
private static validateImages(files: FileList): any[] {
const result = [];
const types = [
'image/jpg',
'image/jpeg',
'image/png'
];
for (let i = 0; i < files.length; i++) {
if (types.includes(files.item(i).type)) {
result.push(files.item(i));
}
}
return result;
}
private static validateDocuments(files: FileList): any[] {
const result = [];
const types = [
'application/pdf'
];
for (let i = 0; i < files.length; i++) {
if (types.includes(files.item(i).type)) {
result.push(files.item(i));
}
}
return result;
}
ngOnInit() {
if (this.fileType && this.fileType === 'document') {
this.accept = 'application/pdf';
}
}
public update(): void {
this._document.getElementById(this.id).click();
}
public onDeletePhoto(): void {
this.isLoaded = false;
this.loadImage.emit(new UserMedia(null, ''));
}
public onChangeFile(event): void {
const files: FileList = event.target.files;
let validImages;
switch (this.fileType) {
case 'image360':
validImages = UploadFileComponent.validateImages(files);
if (validImages.length < files.length) {
this._snackBarService.setMessage(
'Suba imagenes con extensiones .jpeg / .jpg / .png solamente.',
'OK',
2000
);
}
if (validImages.length > 0) {
this.createImages360(validImages);
}
break;
case 'document':
const validDocuments = UploadFileComponent.validateDocuments(files);
if (validDocuments.length < files.length) {
this._snackBarService.setMessage('Suba archivos con extensión .pdf solamente.', 'OK', 2000);
}
if (validDocuments.length > 0) {
this.createDocuments(validDocuments);
}
break;
default:
validImages = UploadFileComponent.validateImages(files);
if (validImages.length < files.length) {
this._snackBarService.setMessage(
'Suba imagenes con extensiones .jpeg / .jpg / .png solamente.',
'OK',
2000
);
}
if (validImages.length > 0) {
this.openCropper(validImages);
}
break;
}
}
private createDocuments(files: any[]): void {
const result = [];
const readDoc = (file: any) => {
let base = null;
const reader = new FileReader();
reader.onload = (event: any) => {
if (base === null) {
base = event.target.result;
reader.readAsArrayBuffer(file);
} else {
result.push(new UserMedia(new Blob([event.target.result]), base));
validate();
}
};
reader.readAsDataURL(file);
};
const validate = () => {
if (files.length > 0) {
const file = files.splice(0, 1);
readDoc(file[0]);
} else {
this.loadImage.emit(result.length === 1 ? result[0] : result);
}
};
validate();
}
private createImages360(files: any[]): void {
const result = [];
let discarded = 0;
const createImage = (file: any) => {
let img;
const reader = new FileReader();
const onLoadImg = () => {
if ((img.width / 2) >= img.height) {
reader.readAsArrayBuffer(file);
} else {
discarded++;
validate();
}
};
reader.onload = (event: any) => {
if (!img) {
img = new Image();
img.src = event.target.result;
img.onload = onLoadImg;
} else {
result.push(new UserMedia(new Blob([event.target.result], {type: file.type}), img.src, PFileTypeEnum.SPHERIC));
validate();
}
};
reader.readAsDataURL(file);
};
const validate = () => {
if (files.length > 0) {
const file = files.splice(0, 1);
createImage(file[0]);
} else {
if (discarded > 0) {
this._snackBarService.setMessage(`Se decartaron ${discarded}`, 'OK', 2000);
}
this.loadImage.emit(result.length === 1 ? result[0] : result);
}
};
validate();
}
private openCropper(files: any[]): void {
this._dialog.open<CropImageComponent, DataCropImage, UserMedia[]>(CropImageComponent,
{
data:
{
aspectRatio: this.aspectRatio,
circle: this.circle,
files: files
},
disableClose: true
}
).afterClosed().subscribe((response) => {
if (!response) {
return;
}
this.loadImage.emit(response.length === 1 ? response[0] : response);
});
}
}
<!--
~ Copyright (C) MapLander S de R.L de C.V - All Rights Reserved
~ Unauthorized copying of this file, via any medium is strictly prohibited
~ Proprietary and confidential
~
-->
<div id="upload-file-component">
<ng-container [ngTemplateOutlet]="content">
<input #fileInput type="file" [accept]="accept" [id]="id" (change)="onChangeFile($event)"
[multiple]="multiple" (click)="fileInput.value = null" class="inputHiddenForFileInComponent"/>
<ng-template [ngIf]="fab" [ngIfElse]="layerWithButtons">
<div class="btn_edit_photo_fab" (click)="update()" [attr.data-disabled-upload]="disabled ? '' : null"></div>
</ng-template>
<ng-template #layerWithButtons>
<div id="buttonHiddenForUploadFileComponent" [attr.data-disabled-upload]="disabled ? '' : null">
<div class="btn_edit_photo" (click)="update()">
<mat-icon>edit</mat-icon>
</div>
<ng-template [ngIf]="isLoaded">
<div class="btn_delete_photo" (click)="onDeletePhoto()">
<mat-icon>delete</mat-icon>
</div>
</ng-template>
</div>
</ng-template>
</ng-container>
</div>
/*!
* Copyright (C) MapLander S de R.L de C.V - All Rights Reserved
* Unauthorized copying of this file, via any medium is strictly prohibited
* Proprietary and confidential
*
*/
:host{
display: block;
width: fit-content;
height: fit-content;
position: inherit;
margin: inherit;
top: inherit;
left: inherit;
right: inherit;
bottom: inherit;
}
[data-disabled-upload]{
display: none;
}
#upload-file-component{
position: relative;
display: flex;
justify-content: center;
width: fit-content;
height: fit-content;
.inputHiddenForFileInComponent{
display: none;
}
#buttonHiddenForUploadFileComponent{
position: absolute;
width: 100%;
height: 100%;
top: 0;
right: 0;
border: 0;
margin: 0;
padding: 0 28px;
background-color: transparent;
}
#buttonHiddenForUploadFileComponent:hover{
& .btn_edit_photo, .btn_delete_photo{
display: initial;
}
}
.btn_edit_photo_fab{
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
cursor: pointer;
background: transparent;
}
.btn_edit_photo{
position: absolute;
bottom: 0;
right: 0;
padding: 4px;
border-radius: 4px;
color: white;
display: none;
cursor: pointer;
background-color: rgba(0, 0, 0, .4);
mat-icon{
width: 20px;
height: 20px;
font-size: 20px;
}
}
.btn_delete_photo{
position: absolute;
bottom: 0;
right: 36px;
padding: 4px;
border-radius: 4px;
color: white;
display: none;
cursor: pointer;
background-color: rgba(0, 0, 0, .4);
mat-icon{
width: 20px;
height: 20px;
font-size: 20px;
}
}
input:focus{
outline: none !important;
}
}
Legend
Html element with directive