File
Implements
Metadata
selector |
lib-property-multimedia-uploader |
styleUrls |
./multimedia-uploader.component.scss |
templateUrl |
./multimedia-uploader.component.html |
Methods
Private
createImage360PFile
|
createImage360PFile(image: UserMedia)
|
|
Parameters :
Name |
Type |
Optional |
image |
UserMedia
|
No
|
|
Private
createImagePFile
|
createImagePFile(image: UserMedia)
|
|
Parameters :
Name |
Type |
Optional |
image |
UserMedia
|
No
|
|
Private
Static
getYouTubeID
|
getYouTubeID(text: string)
|
|
Parameters :
Name |
Type |
Optional |
text |
string
|
No
|
|
Private
joinMultimediaTypes
|
joinMultimediaTypes()
|
|
Returns : PFile[]
|
onListChanged
|
onListChanged(ev: PFile[])
|
|
Parameters :
Name |
Type |
Optional |
ev |
PFile[]
|
No
|
|
onTabChanged
|
onTabChanged(tab: number)
|
|
Parameters :
Name |
Type |
Optional |
tab |
number
|
No
|
|
onUploadImage
|
onUploadImage(ev: UserMedia | UserMedia[])
|
|
Parameters :
Name |
Type |
Optional |
ev |
UserMedia | UserMedia[]
|
No
|
|
onYouTubeInputTextChanged
|
onYouTubeInputTextChanged(input: HTMLInputElement)
|
|
Parameters :
Name |
Type |
Optional |
input |
HTMLInputElement
|
No
|
|
Private
parseMultimedia
|
parseMultimedia()
|
|
|
removeMedia
|
removeMedia(ev: PFile)
|
|
Parameters :
Name |
Type |
Optional |
ev |
PFile
|
No
|
|
Private
_newMedia
|
Type : UserMedia[]
|
|
Public
currentIndex
|
Type : number
|
|
Public
fileType
|
Type : "image" | "image360" | "document"
|
|
Public
images
|
Type : PFile[]
|
|
Public
images360
|
Type : PFile[]
|
|
Public
videos
|
Type : PFile[]
|
|
import {Component, Inject, OnInit} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
import {PFile, PFileTypeEnum, UserMedia} from '@maplander/types';
interface MultimediaUploaderData {
currentType: PFileTypeEnum;
multimedia: PFile[];
newMedia: UserMedia[];
}
@Component({
selector: 'lib-property-multimedia-uploader',
templateUrl: './multimedia-uploader.component.html',
styleUrls: ['./multimedia-uploader.component.scss']
})
export class MultimediaUploaderComponent implements OnInit {
public fileType: 'image' | 'image360' | 'document';
public images: PFile[];
public images360: PFile[];
public videos: PFile[];
public currentIndex: number;
private _newMedia: UserMedia[];
constructor(
@Inject(MAT_DIALOG_DATA) private _data: MultimediaUploaderData,
private _dialog: MatDialogRef<MultimediaUploaderComponent, { multimedia: PFile[], newMedia: UserMedia[] }>
) {
switch (this._data.currentType) {
case PFileTypeEnum.IMAGE:
this.fileType = 'image';
this.currentIndex = 0;
break;
case PFileTypeEnum.SPHERIC:
this.fileType = 'image360';
this.currentIndex = 1;
break;
case PFileTypeEnum.VIDEO:
this.fileType = 'document';
this.currentIndex = 2;
break;
}
this.images = [];
this.images360 = [];
this.videos = [];
this._newMedia = [];
}
private static getYouTubeID(text: string): string {
if (text.indexOf('https://youtu.be/') !== -1) {
text = text.replace('https://youtu.be/', '');
} else if (text.indexOf('https://www.youtube.com/') !== -1) {
text = text.replace('https://www.youtube.com/', '');
} else {
return text = null;
}
if (text.indexOf('watch?v=') !== -1) {
text = text.replace('watch?v=', '');
} else {
return text = null;
}
return text;
}
ngOnInit() {
this.parseMultimedia();
}
onUploadImage(ev: UserMedia | UserMedia[]): void {
if (!ev) {
return;
}
switch (this.fileType) {
case 'image':
if (Array.isArray(ev)) {
ev.forEach(image => {
this.createImagePFile(image);
});
} else {
this.createImagePFile(ev);
}
break;
case 'image360':
if (Array.isArray(ev)) {
ev.forEach(image => {
this.createImage360PFile(image);
});
} else {
this.createImage360PFile(ev);
}
break;
}
}
onTabChanged(tab: number): void {
this.currentIndex = tab;
switch (tab) {
case 0:
this.fileType = 'image';
break;
case 1:
this.fileType = 'image360';
break;
}
}
onListChanged(ev: PFile[]): void {
switch (this.currentIndex) {
case 0:
if (Array.isArray(ev) && ev.length > 0) {
ev = ev.map((item, index) => {
item.position = index;
return item;
});
this.images = ev;
}
break;
case 1:
if (Array.isArray(ev) && ev.length > 0) {
ev = ev.map((item, index) => {
item.position = index;
return item;
});
this.images360 = ev;
}
break;
case 2:
if (Array.isArray(ev) && ev.length > 0) {
ev = ev.map((item, index) => {
item.position = index;
return item;
});
this.videos = ev;
}
break;
}
}
removeMedia(ev: PFile): void {
let i = -1;
if (!ev.id) {
switch (ev.type) {
case PFileTypeEnum.IMAGE:
this.images.splice(this.images.indexOf(ev), 1);
break;
case PFileTypeEnum.SPHERIC:
this.images360.splice(this.images360.indexOf(ev), 1);
break;
case PFileTypeEnum.VIDEO:
this.videos.splice(this.videos.indexOf(ev), 1);
break;
}
this._newMedia.forEach((item, index) => {
if (item.url === ev.fileCS.thumbnail) {
i = index;
}
});
if (i > -1) {
this._newMedia.splice(i, 1);
}
} else {
switch (ev.type) {
case PFileTypeEnum.IMAGE:
this.images.splice(this.images.indexOf(ev), 1);
break;
case PFileTypeEnum.SPHERIC:
this.images360.splice(this.images360.indexOf(ev), 1);
break;
case PFileTypeEnum.VIDEO:
this.videos.splice(this.videos.indexOf(ev), 1);
break;
}
}
}
onYouTubeInputTextChanged(input: HTMLInputElement): void {
if (input.value === '') {
return;
}
const id = MultimediaUploaderComponent.getYouTubeID(input.value);
if (!id) {
return;
}
if (id.length >= 11) {
const file = new PFile();
file.type = PFileTypeEnum.VIDEO;
file.media = true;
file.name = `video_${new Date().getTime()}`;
file.fileCS = {
thumbnail: id,
blobName: null
};
file.position = this.videos.length === 0 ? 0 : this.videos.length;
this.videos.push(file);
input.value = '';
}
}
accept(): void {
this._dialog.close({multimedia: this.joinMultimediaTypes(), newMedia: this._newMedia});
}
close(): void {
this._dialog.close(null);
}
private createImagePFile(image: UserMedia): void {
const file = new PFile();
file.type = PFileTypeEnum.IMAGE;
image.type = PFileTypeEnum.IMAGE;
file.media = true;
file.fileCS = {
thumbnail: image.url,
blobName: null
};
const fileName = `image_${Date.now()}_${Math.round(Math.random() * 1000000)}.${image.blob.type.replace('image/', '')}`;
file.name = fileName;
image.name = fileName;
file.position = this.images.length === 0 ? 0 : this.images.length;
this._newMedia.push(image);
this.images.push(file);
}
private createImage360PFile(image: UserMedia): void {
const file = new PFile();
file.type = PFileTypeEnum.SPHERIC;
image.type = PFileTypeEnum.SPHERIC;
file.media = true;
const fileName = `spheric_${Date.now()}_${Math.round(Math.random() * 1000000)}.${image.blob.type.replace('image/', '')}`;
file.name = fileName;
image.name = fileName;
file.fileCS = {
thumbnail: image.url,
blobName: null
};
file.position = this.images360.length === 0 ? 0 : this.images360.length;
this._newMedia.push(image);
this.images360.push(file);
}
private parseMultimedia(): void {
if (this._data) {
this._data.multimedia.forEach(item => {
switch (item.type) {
case PFileTypeEnum.IMAGE:
this.images.push(item);
break;
case PFileTypeEnum.SPHERIC:
this.images360.push(item);
break;
case PFileTypeEnum.VIDEO:
this.videos.push(item);
break;
}
});
this._newMedia = this._data.newMedia || [];
}
}
private joinMultimediaTypes(): PFile[] {
let response = [];
response = response.concat(this.images);
response = response.concat(this.images360);
response = response.concat(this.videos);
return response;
}
}
<div class="multimedia-uploader">
<p class="title">
Multimedia
<ng-template [ngIf]="currentIndex !== 2">
<lib-upload-file [content]="buttonUploadTemplate" [fab]="true" [fileType]="fileType" [aspectRatio]="4 / 3"
[multiple]="true"
(loadImage)="onUploadImage($event)">
<ng-template #buttonUploadTemplate>
<button mat-icon-button color="primary">
<mat-icon>add</mat-icon>
</button>
</ng-template>
</lib-upload-file>
</ng-template>
</p>
<mat-tab-group class="multimedia-uploader__tab-group" [selectedIndex]="currentIndex"
(selectedIndexChange)="onTabChanged($event)">
<mat-tab label="Fotografias">
<lib-custom-drag-and-drop [items]="images" [content]="imageTemplate" (itemsChanged)="onListChanged($event)">
<ng-template #imageTemplate let-image="image" let-index="index">
<div class="list__item" [ngClass]="{'first-photo': index === 0}">
<img alt="Property image" [src]="image.fileCS.thumbnail" class="list__item-img">
<button mat-icon-button class="list__item-button mat-elevation-z2" (click)="removeMedia(image)">
<mat-icon class="list__item-icon">close</mat-icon>
</button>
</div>
</ng-template>
</lib-custom-drag-and-drop>
</mat-tab>
<mat-tab label="Esfericas">
<lib-custom-drag-and-drop [items]="images360" [content]="image360Template" (itemsChanged)="onListChanged($event)">
<ng-template #image360Template let-image="image">
<div class="list__item">
<img alt="Property image" [src]="image.fileCS.thumbnail" class="list__item-img">
<button mat-icon-button class="list__item-button mat-elevation-z2" (click)="removeMedia(image)">
<mat-icon class="list__item-icon">close</mat-icon>
</button>
</div>
</ng-template>
</lib-custom-drag-and-drop>
</mat-tab>
<mat-tab label="Videos">
<div class="you-tube-container">
<span class="you-tube-container__searchbox">
<button *ngIf="inputYouTube.value !== ''" mat-icon-button class="you-tube-container__close-btn"
(click)="inputYouTube.value = ''"><mat-icon>close</mat-icon></button>
<input class="you-tube-container__input" #inputYouTube (input)="onYouTubeInputTextChanged(inputYouTube)"
title="YouTube URL" placeholder="YouTube URL o YouTube Video ID">
</span>
<a href="https://www.youtube.com" target="_blank" mat-button color="primary">
Ir a Youtube
</a>
</div>
<lib-custom-drag-and-drop [items]="videos" [content]="videosTemplate" (itemsChanged)="onListChanged($event)">
<ng-template #videosTemplate let-image="image">
<div class="list__item">
<img alt="Property image" [src]="'http://i3.ytimg.com/vi/'+image.fileCS.thumbnail+'/hqdefault.jpg'"
class="list__item-img">
<button mat-icon-button class="list__item-button mat-elevation-z2" (click)="removeMedia(image)">
<mat-icon class="list__item-icon">close</mat-icon>
</button>
</div>
</ng-template>
</lib-custom-drag-and-drop>
</mat-tab>
</mat-tab-group>
<div class="multimedia-uploader__actions">
<button mat-flat-button color="primary" class="actions__button" (click)="close()">
CERRAR
</button>
<button mat-flat-button color="primary" class="actions__button" (click)="accept()">
ACEPTAR
</button>
</div>
</div>
:host {
display: block;
width: 100%;
height: 100%;
}
::ng-deep .multimedia-uploader-panel-class {
width: 50%;
height: 70%;
mat-dialog-container {
width: 100%;
height: 100%;
padding: 16px;
overflow: hidden;
position: relative;
}
@media screen and (max-width: 600px) {
width: 100% !important;
max-width: 100% !important;
height: 100% !important;
}
}
.multimedia-uploader {
width: 100%;
height: 100%;
}
.multimedia-uploader__actions {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
background: white;
z-index: 1;
}
.actions__button {
width: 50%;
}
.actions__button:first-child {
border-radius: 8px 0 0 0;
}
.actions__button:last-child {
border-radius: 0 8px 0 0;
}
.title {
font-weight: bold;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px;
margin: 0;
}
.multimedia-uploader__tab-group {
width: 100%;
height: calc(100% - 36px);
}
.multimedia-uploader__list {
width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: auto;
display: grid;
grid-template-columns: repeat(3, calc(100% / 3));
@media screen and (max-width: 600px){
grid-template-columns: 100%;
}
}
.list__item {
width: 200px;
height: 150px;
border-radius: 8px;
margin: 16px auto;
position: relative;
}
.first-photo:after {
content: 'Imagen principal del anuncio';
position: absolute;
top: 0;
padding: 8px;
box-sizing: border-box;
font-size: 12px;
width: 100%;
color: white;
background: rgba(0, 0, 0, .3);
}
.list__item-img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 8px;
}
.list__item-button {
position: absolute;
width: 24px;
height: 24px;
top: -12px;
right: -12px;
background: black;
color: white;
}
.list__item-icon {
width: 24px;
height: 24px;
font-size: 16px;
line-height: 8px;
}
.you-tube-container {
display: flex;
padding: 8px 0;
box-sizing: border-box;
justify-content: space-between;
position: sticky;
top: 0;
z-index: 5;
background: white;
}
.you-tube-container__searchbox {
position: relative;
width: calc(100% - 120px);
box-sizing: border-box;
display: flex;
align-items: center;
}
.you-tube-container__close-btn {
position: absolute;
right: 0;
}
.you-tube-container__input {
width: 100%;
border: 1px solid lightgrey;
padding: 8px 32px 8px 8px;
border-radius: 8px;
outline: none;
}
Legend
Html element with directive