@dataclouder/ngx-cloud-storage 0.0.30 → 0.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,30 +1,38 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Injectable, input, output, ViewChild, Component, Pipe, ChangeDetectorRef, Input, signal, computed } from '@angular/core';
|
|
2
|
+
import { inject, Injectable, input, output, ViewChild, Component, Pipe, ChangeDetectorRef, Input, signal, InjectionToken, EventEmitter, Output, computed } from '@angular/core';
|
|
3
3
|
import { ImageCropperComponent } from 'ngx-image-cropper';
|
|
4
4
|
import * as i1 from '@angular/forms';
|
|
5
5
|
import { FormsModule } from '@angular/forms';
|
|
6
6
|
import { AngularFireStorage } from '@angular/fire/compat/storage';
|
|
7
7
|
import { getStorage, ref, listAll, deleteObject, getDownloadURL, Storage } from '@angular/fire/storage';
|
|
8
|
-
import { lastValueFrom, BehaviorSubject } from 'rxjs';
|
|
9
|
-
import * as
|
|
8
|
+
import { lastValueFrom, BehaviorSubject, firstValueFrom } from 'rxjs';
|
|
9
|
+
import * as i4 from 'primeng/dialog';
|
|
10
10
|
import { DialogModule } from 'primeng/dialog';
|
|
11
|
-
import * as
|
|
11
|
+
import * as i5 from 'primeng/tooltip';
|
|
12
12
|
import { TooltipModule } from 'primeng/tooltip';
|
|
13
13
|
import * as i2 from 'primeng/button';
|
|
14
14
|
import { ButtonModule } from 'primeng/button';
|
|
15
|
-
import * as
|
|
15
|
+
import * as i6 from 'primeng/message';
|
|
16
16
|
import { MessageModule } from 'primeng/message';
|
|
17
|
-
import * as
|
|
17
|
+
import * as i7 from 'primeng/select';
|
|
18
18
|
import { SelectModule } from 'primeng/select';
|
|
19
|
-
import * as
|
|
19
|
+
import * as i8 from 'primeng/inputtext';
|
|
20
20
|
import { InputTextModule } from 'primeng/inputtext';
|
|
21
|
-
import { MoodStateOptions, CharacterEventActions } from '@dataclouder/ngx-core';
|
|
22
|
-
import { FieldsetModule } from 'primeng/fieldset';
|
|
21
|
+
import { MoodStateOptions, CharacterEventActions, APP_CONFIG } from '@dataclouder/ngx-core';
|
|
23
22
|
import * as i1$1 from '@angular/platform-browser';
|
|
24
|
-
import { DynamicDialogRef, DynamicDialogConfig, DialogService, DynamicDialogModule } from 'primeng/dynamicdialog';
|
|
25
23
|
import * as i3 from 'primeng/api';
|
|
24
|
+
import * as i1$2 from '@angular/common';
|
|
26
25
|
import { AsyncPipe, CommonModule } from '@angular/common';
|
|
27
|
-
import
|
|
26
|
+
import { HttpClient } from '@angular/common/http';
|
|
27
|
+
import * as i2$1 from 'primeng/fileupload';
|
|
28
|
+
import { FileUploadModule } from 'primeng/fileupload';
|
|
29
|
+
import * as i3$1 from 'primeng/toast';
|
|
30
|
+
import { ToastModule } from 'primeng/toast';
|
|
31
|
+
import * as i4$1 from 'primeng/progressbar';
|
|
32
|
+
import { ProgressBarModule } from 'primeng/progressbar';
|
|
33
|
+
import * as i5$1 from 'primeng/badge';
|
|
34
|
+
import { BadgeModule } from 'primeng/badge';
|
|
35
|
+
import * as i3$2 from 'primeng/tag';
|
|
28
36
|
import { TagModule } from 'primeng/tag';
|
|
29
37
|
|
|
30
38
|
const AspectRatioOptions = [
|
|
@@ -71,6 +79,7 @@ const AspectRatioOptions = [
|
|
|
71
79
|
low: { w: 360, h: 640 },
|
|
72
80
|
sd: { w: 450, h: 800 },
|
|
73
81
|
sdLarge: { w: 540, h: 960 },
|
|
82
|
+
semiHd: { w: 630, h: 1120 },
|
|
74
83
|
hd: { w: 720, h: 1280 },
|
|
75
84
|
fullhd: { w: 1080, h: 1920 },
|
|
76
85
|
'4k': { w: 2160, h: 3840 },
|
|
@@ -378,10 +387,10 @@ class MultiImagesStorageService {
|
|
|
378
387
|
return null;
|
|
379
388
|
}
|
|
380
389
|
}
|
|
381
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
382
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
390
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: MultiImagesStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
391
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: MultiImagesStorageService, providedIn: 'root' }); }
|
|
383
392
|
}
|
|
384
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
393
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: MultiImagesStorageService, decorators: [{
|
|
385
394
|
type: Injectable,
|
|
386
395
|
args: [{
|
|
387
396
|
providedIn: 'root',
|
|
@@ -450,13 +459,13 @@ class CropperComponent {
|
|
|
450
459
|
closeModal() {
|
|
451
460
|
this.showModal = false;
|
|
452
461
|
}
|
|
453
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
454
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
462
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: CropperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
463
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: CropperComponent, isStandalone: true, selector: "app-cropper", inputs: { imageSettings: { classPropertyName: "imageSettings", publicName: "imageSettings", isSignal: true, isRequired: false, transformFunction: null }, ratioType: { classPropertyName: "ratioType", publicName: "ratioType", isSignal: true, isRequired: false, transformFunction: null }, resolutions: { classPropertyName: "resolutions", publicName: "resolutions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { imageUploaded: "imageUploaded", onImageCropped: "onImageCropped", onFileSelected: "onFileSelected" }, viewQueries: [{ propertyName: "imageCropper", first: true, predicate: ImageCropperComponent, descendants: true }], ngImport: i0, template: "<div> path: {{ storagePath }} </div>\n\n<div class=\"options\">\n @if (!isUploaded) {\n <div>\n <input type=\"file\" id=\"file-upload\" class=\"file-input\" (change)=\"fileChangeEvent($event)\" />\n <label for=\"file-upload\" class=\"btn-upload\">Seleccionar archivo</label>\n @if (!fileMetadata) {\n <em>Carga una imagen para comenzar</em>\n }\n </div>\n }\n\n @if (fileMetadata) {\n <span>\n <span style=\"margin: 1px 20px\"> tipo: {{ fileMetadata.type }} </span>\n <span style=\"margin: 1px 20px\"> tama\u00F1o {{ fileMetadata.size }} </span>\n <br />\n <input\n [disabled]=\"imageSettings()?.fileName\"\n style=\"margin: 1px 20px; width: 400px\"\n [(ngModel)]=\"renameFile\"\n type=\"text\"\n placeholder=\"Rename File\"\n (ngModelChange)=\"reloadPath()\" />\n <button class=\"btn-crop\" (click)=\"closeModal()\"> Recortar y Subir </button>\n </span>\n }\n</div>\n\n@if (fileMetadata && !isUploaded) {\n <div class=\"modal\" [class.show-modal]=\"showModal\">\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h3>Recortar imagen</h3>\n <button class=\"close-button\" (click)=\"closeModal()\">\u00D7</button>\n </div>\n <div class=\"modal-body\">\n <h1>Hlloa</h1>\n <image-cropper\n [imageChangedEvent]=\"imageChangedEvent\"\n [maintainAspectRatio]=\"true\"\n [aspectRatio]=\"aspectRatio\"\n format=\"webp\"\n [resizeToWidth]=\"450\"\n (imageCropped)=\"onInnerImageCropped($event)\"\n (loadImageFailed)=\"loadImageFailed()\"\n (imageLoaded)=\"imageLoaded($event)\"\n [autoCrop]=\"false\"></image-cropper>\n <div class=\"modal-footer\">\n <button class=\"btn-crop\" (click)=\"simpleCropAndUpload()\">Recortar y Subir</button>\n </div>\n </div>\n </div>\n </div>\n}\n\n@if (croppedImage && !isUploaded) {\n <button [disabled]=\"isLoading\" nbButton status=\"info\"> upload </button>\n}\n", styles: [".options{display:flex}.btn-crop{cursor:pointer;outline:0;display:inline-block;font-weight:400;line-height:1.5;text-align:center;background-color:transparent;border:1px solid transparent;padding:6px 12px;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;color:#0d6efd;border-color:#0d6efd}.btn-crop :hover{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.file-input{display:none}.btn-upload{cursor:pointer;outline:0;display:inline-block;font-weight:400;line-height:1.5;text-align:center;background-color:transparent;border:1px solid #0d6efd;padding:6px 12px;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;color:#0d6efd}.btn-upload:hover{color:#fff;background-color:#0d6efd}.modal{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;z-index:1000}.modal.show-modal{display:flex;align-items:center;justify-content:center}.modal .modal-content{background-color:#fff;border-radius:8px;width:90%;max-width:800px;max-height:90vh;overflow-y:auto;position:relative}.modal .modal-header{padding:1rem;border-bottom:1px solid #dee2e6;display:flex;justify-content:space-between;align-items:center}.modal .modal-header h3{margin:0}.modal .modal-header .close-button{background:none;border:none;font-size:1.5rem;cursor:pointer;padding:0;color:#6c757d}.modal .modal-header .close-button:hover{color:#343a40}.modal .modal-body{padding:1rem}.modal .modal-footer{padding:1rem;border-top:1px solid #dee2e6;display:flex;justify-content:flex-end}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ImageCropperComponent, selector: "image-cropper", inputs: ["imageChangedEvent", "imageURL", "imageBase64", "imageFile", "imageAltText", "options", "cropperFrameAriaLabel", "output", "format", "autoCrop", "cropper", "transform", "maintainAspectRatio", "aspectRatio", "resetCropOnAspectRatioChange", "resizeToWidth", "resizeToHeight", "cropperMinWidth", "cropperMinHeight", "cropperMaxHeight", "cropperMaxWidth", "cropperStaticWidth", "cropperStaticHeight", "canvasRotation", "initialStepSize", "roundCropper", "onlyScaleDown", "imageQuality", "backgroundColor", "containWithinAspectRatio", "hideResizeSquares", "allowMoveImage", "checkImageType", "alignImage", "disabled", "hidden"], outputs: ["imageCropped", "startCropImage", "imageLoaded", "cropperReady", "loadImageFailed", "transformChange", "cropperChange"] }] }); }
|
|
455
464
|
}
|
|
456
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
465
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: CropperComponent, decorators: [{
|
|
457
466
|
type: Component,
|
|
458
467
|
args: [{ selector: 'app-cropper', standalone: true, imports: [FormsModule, ImageCropperComponent], template: "<div> path: {{ storagePath }} </div>\n\n<div class=\"options\">\n @if (!isUploaded) {\n <div>\n <input type=\"file\" id=\"file-upload\" class=\"file-input\" (change)=\"fileChangeEvent($event)\" />\n <label for=\"file-upload\" class=\"btn-upload\">Seleccionar archivo</label>\n @if (!fileMetadata) {\n <em>Carga una imagen para comenzar</em>\n }\n </div>\n }\n\n @if (fileMetadata) {\n <span>\n <span style=\"margin: 1px 20px\"> tipo: {{ fileMetadata.type }} </span>\n <span style=\"margin: 1px 20px\"> tama\u00F1o {{ fileMetadata.size }} </span>\n <br />\n <input\n [disabled]=\"imageSettings()?.fileName\"\n style=\"margin: 1px 20px; width: 400px\"\n [(ngModel)]=\"renameFile\"\n type=\"text\"\n placeholder=\"Rename File\"\n (ngModelChange)=\"reloadPath()\" />\n <button class=\"btn-crop\" (click)=\"closeModal()\"> Recortar y Subir </button>\n </span>\n }\n</div>\n\n@if (fileMetadata && !isUploaded) {\n <div class=\"modal\" [class.show-modal]=\"showModal\">\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h3>Recortar imagen</h3>\n <button class=\"close-button\" (click)=\"closeModal()\">\u00D7</button>\n </div>\n <div class=\"modal-body\">\n <h1>Hlloa</h1>\n <image-cropper\n [imageChangedEvent]=\"imageChangedEvent\"\n [maintainAspectRatio]=\"true\"\n [aspectRatio]=\"aspectRatio\"\n format=\"webp\"\n [resizeToWidth]=\"450\"\n (imageCropped)=\"onInnerImageCropped($event)\"\n (loadImageFailed)=\"loadImageFailed()\"\n (imageLoaded)=\"imageLoaded($event)\"\n [autoCrop]=\"false\"></image-cropper>\n <div class=\"modal-footer\">\n <button class=\"btn-crop\" (click)=\"simpleCropAndUpload()\">Recortar y Subir</button>\n </div>\n </div>\n </div>\n </div>\n}\n\n@if (croppedImage && !isUploaded) {\n <button [disabled]=\"isLoading\" nbButton status=\"info\"> upload </button>\n}\n", styles: [".options{display:flex}.btn-crop{cursor:pointer;outline:0;display:inline-block;font-weight:400;line-height:1.5;text-align:center;background-color:transparent;border:1px solid transparent;padding:6px 12px;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;color:#0d6efd;border-color:#0d6efd}.btn-crop :hover{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.file-input{display:none}.btn-upload{cursor:pointer;outline:0;display:inline-block;font-weight:400;line-height:1.5;text-align:center;background-color:transparent;border:1px solid #0d6efd;padding:6px 12px;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;color:#0d6efd}.btn-upload:hover{color:#fff;background-color:#0d6efd}.modal{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;z-index:1000}.modal.show-modal{display:flex;align-items:center;justify-content:center}.modal .modal-content{background-color:#fff;border-radius:8px;width:90%;max-width:800px;max-height:90vh;overflow-y:auto;position:relative}.modal .modal-header{padding:1rem;border-bottom:1px solid #dee2e6;display:flex;justify-content:space-between;align-items:center}.modal .modal-header h3{margin:0}.modal .modal-header .close-button{background:none;border:none;font-size:1.5rem;cursor:pointer;padding:0;color:#6c757d}.modal .modal-header .close-button:hover{color:#343a40}.modal .modal-body{padding:1rem}.modal .modal-footer{padding:1rem;border-top:1px solid #dee2e6;display:flex;justify-content:flex-end}\n"] }]
|
|
459
|
-
}], propDecorators: { imageCropper: [{
|
|
468
|
+
}], propDecorators: { imageSettings: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageSettings", required: false }] }], ratioType: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratioType", required: false }] }], resolutions: [{ type: i0.Input, args: [{ isSignal: true, alias: "resolutions", required: false }] }], imageUploaded: [{ type: i0.Output, args: ["imageUploaded"] }], onImageCropped: [{ type: i0.Output, args: ["onImageCropped"] }], onFileSelected: [{ type: i0.Output, args: ["onFileSelected"] }], imageCropper: [{
|
|
460
469
|
type: ViewChild,
|
|
461
470
|
args: [ImageCropperComponent]
|
|
462
471
|
}] } });
|
|
@@ -468,10 +477,10 @@ class SafeHtmlPipe {
|
|
|
468
477
|
transform(value) {
|
|
469
478
|
return this.sanitizer.bypassSecurityTrustHtml(value);
|
|
470
479
|
}
|
|
471
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
472
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "
|
|
480
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: SafeHtmlPipe, deps: [{ token: i1$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
481
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.2", ngImport: i0, type: SafeHtmlPipe, isStandalone: true, name: "safeHtml" }); }
|
|
473
482
|
}
|
|
474
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
483
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: SafeHtmlPipe, decorators: [{
|
|
475
484
|
type: Pipe,
|
|
476
485
|
args: [{
|
|
477
486
|
name: 'safeHtml',
|
|
@@ -483,9 +492,6 @@ class CropperComponentModal {
|
|
|
483
492
|
constructor() {
|
|
484
493
|
this.multiImagesStorageService = inject(MultiImagesStorageService);
|
|
485
494
|
this.changeDetectorRef = inject(ChangeDetectorRef);
|
|
486
|
-
this.ref = inject(DynamicDialogRef, { optional: true });
|
|
487
|
-
this.config = inject(DynamicDialogConfig, { optional: true });
|
|
488
|
-
this.dialogService = inject(DialogService);
|
|
489
495
|
// overrides name, path and resizeToWidth
|
|
490
496
|
this.imgStorageSettings = input(DEFAULT_SETTINGS, ...(ngDevMode ? [{ debugName: "imgStorageSettings" }] : []));
|
|
491
497
|
this.buttonLabel = input('Seleccionar archivo', ...(ngDevMode ? [{ debugName: "buttonLabel" }] : []));
|
|
@@ -496,6 +502,7 @@ class CropperComponentModal {
|
|
|
496
502
|
this.aspectRatioOptions = AspectRatioOptions;
|
|
497
503
|
this.MoodStateOptions = MoodStateOptions;
|
|
498
504
|
this.fileMetadata = null;
|
|
505
|
+
this.displayDialog = false;
|
|
499
506
|
this.aspectRatioValue = 1;
|
|
500
507
|
this.croppedImage = '';
|
|
501
508
|
this.renameFile = '';
|
|
@@ -510,12 +517,6 @@ class CropperComponentModal {
|
|
|
510
517
|
if (!this.imgStorageSettings().path) {
|
|
511
518
|
console.warn('⚠️ Remember to set imgStorageSettings, path and fileName are required , path example: /collection/id/subcollection ');
|
|
512
519
|
}
|
|
513
|
-
// This happens when the component is opened as a dialog
|
|
514
|
-
if (this.config?.data) {
|
|
515
|
-
this.imageChangedEvent = this.config.data.imageChangedEvent;
|
|
516
|
-
this.fileMetadata = this.config.data.file;
|
|
517
|
-
}
|
|
518
|
-
this.setSettingsForComponent();
|
|
519
520
|
this.reloadPath();
|
|
520
521
|
}
|
|
521
522
|
reloadPath() {
|
|
@@ -524,60 +525,48 @@ class CropperComponentModal {
|
|
|
524
525
|
this.storagePath = `${this.imgStorageSettings().path}/${fileName}-${randomCharacters}.webp`;
|
|
525
526
|
}
|
|
526
527
|
setSettingsForComponent() {
|
|
527
|
-
const
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
this.resizeToWidth = resizeToWidth;
|
|
542
|
-
}
|
|
528
|
+
const imgStorageSettings = this.imgStorageSettings();
|
|
529
|
+
console.log('setSettingsForComponent', imgStorageSettings);
|
|
530
|
+
// TODO: remove all the imageSettings and keep only imgStorageSettings
|
|
531
|
+
this.aspectRatioValue = imgStorageSettings?.cropSettings?.aspectRatio
|
|
532
|
+
? AspectRatio[imgStorageSettings?.cropSettings?.aspectRatio]
|
|
533
|
+
: AspectRatio[AspectType.Square];
|
|
534
|
+
if (imgStorageSettings?.path) {
|
|
535
|
+
this.storagePath = `${imgStorageSettings.path}/${imgStorageSettings.fileName}.webp`;
|
|
536
|
+
}
|
|
537
|
+
else if (imgStorageSettings.path) {
|
|
538
|
+
this.storagePath = `${imgStorageSettings.path}/${imgStorageSettings.fileName}.webp`;
|
|
539
|
+
}
|
|
540
|
+
if (imgStorageSettings?.cropSettings?.resizeToWidth) {
|
|
541
|
+
this.resizeToWidth = imgStorageSettings.cropSettings.resizeToWidth;
|
|
543
542
|
}
|
|
544
|
-
if (
|
|
545
|
-
this.
|
|
543
|
+
else if (imgStorageSettings.cropSettings.resizeToWidth) {
|
|
544
|
+
this.resizeToWidth = imgStorageSettings.cropSettings.resizeToWidth;
|
|
546
545
|
}
|
|
547
|
-
if (fileName) {
|
|
548
|
-
this.renameFile = fileName;
|
|
546
|
+
if (imgStorageSettings?.fileName) {
|
|
547
|
+
this.renameFile = imgStorageSettings.fileName;
|
|
548
|
+
}
|
|
549
|
+
else if (imgStorageSettings.fileName) {
|
|
550
|
+
this.renameFile = imgStorageSettings.fileName;
|
|
549
551
|
}
|
|
550
552
|
}
|
|
551
553
|
async fileChangeEvent(event) {
|
|
552
554
|
this.setSettingsForComponent();
|
|
555
|
+
console.log(this.fileInputId);
|
|
556
|
+
this.imageChangedEvent = event;
|
|
553
557
|
const file = event?.target?.files[0];
|
|
554
558
|
if (file) {
|
|
555
|
-
this.dialogService
|
|
556
|
-
.open(CropperComponentModal, {
|
|
557
|
-
header: 'Recortar y subir imagen',
|
|
558
|
-
width: '70vw',
|
|
559
|
-
modal: true,
|
|
560
|
-
closable: true,
|
|
561
|
-
maximizable: true,
|
|
562
|
-
data: {
|
|
563
|
-
imageChangedEvent: event,
|
|
564
|
-
file: file,
|
|
565
|
-
},
|
|
566
|
-
})
|
|
567
|
-
.onClose.subscribe((result) => {
|
|
568
|
-
if (result) {
|
|
569
|
-
this.imageUploaded.emit(result);
|
|
570
|
-
}
|
|
571
|
-
});
|
|
572
559
|
this.fileMetadata = file;
|
|
573
560
|
this.onFileSelected.emit(file);
|
|
574
561
|
this.renameFile = this.fileMetadata?.name
|
|
575
562
|
?.split('.')[0]
|
|
576
563
|
.replace(/[^a-zA-Z0-9]/g, '')
|
|
577
564
|
.slice(0, 80);
|
|
565
|
+
console.log(this.renameFile);
|
|
578
566
|
if (!this.imgStorageSettings().fileName) {
|
|
579
567
|
this.reloadPath();
|
|
580
568
|
}
|
|
569
|
+
this.displayDialog = true;
|
|
581
570
|
this.changeDetectorRef.detectChanges();
|
|
582
571
|
}
|
|
583
572
|
}
|
|
@@ -605,7 +594,7 @@ class CropperComponentModal {
|
|
|
605
594
|
}
|
|
606
595
|
console.log('imgStorage', imgStorage);
|
|
607
596
|
this.imageUploaded.emit({ ...imgStorage, metadata: this.emotionSelected });
|
|
608
|
-
this.
|
|
597
|
+
this.displayDialog = false;
|
|
609
598
|
this.changeDetectorRef.detectChanges();
|
|
610
599
|
}
|
|
611
600
|
changeRatio(event) {
|
|
@@ -619,27 +608,15 @@ class CropperComponentModal {
|
|
|
619
608
|
console.log('addEmotion', event);
|
|
620
609
|
this.emotionSelected = event;
|
|
621
610
|
}
|
|
622
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
623
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: CropperComponentModal, isStandalone: true, selector: "dc-cropper-modal", inputs: { imgStorageSettings: { classPropertyName: "imgStorageSettings", publicName: "imgStorageSettings", isSignal: true, isRequired: false, transformFunction: null }, buttonLabel: { classPropertyName: "buttonLabel", publicName: "buttonLabel", isSignal: true, isRequired: false, transformFunction: null }, currentStorage: { classPropertyName: "currentStorage", publicName: "currentStorage", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { imageUploaded: "imageUploaded", onImageCropped: "onImageCropped", onFileSelected: "onFileSelected" }, providers: [DialogService], viewQueries: [{ propertyName: "imageCropper", first: true, predicate: ImageCropperComponent, descendants: true }], ngImport: i0, template: "<!-- src/app/components/cropper-modal/cropper-modal.component.html -->\n@if(!config?.data) {\n<div class=\"upload-section\">\n <input type=\"file\" [id]=\"fileInputId\" class=\"file-input\" (change)=\"fileChangeEvent($event)\" />\n <label pButton [for]=\"fileInputId\" [pTooltip]=\"storagePath\" class=\"upload-button\">\n {{ buttonLabel() }}\n </label>\n</div>\n} @else {\n<!-- Image Settings Section -->\n<div class=\"settings-section\">\n @if(!imgStorageSettings().path) {\n <p-message severity=\"warn\">Developer Note: make sure you have a path to save the image pass object imgStorageSettings</p-message>\n } @if(currentStorage?.url) {\n <p-message severity=\"warn\" variant=\"outlined\">\n <div>\n <span class=\"setting-label\">Image will be replaced:</span>\n <img width=\"100\" height=\"Auto\" [src]=\"currentStorage?.url\" />\n </div>\n </p-message>\n }\n\n <div class=\"grid\">\n <div class=\"col-12 md:col-6\">\n <p-message>\n <b>Estas opciones estan preconfiguradas y no se pueden cambiar</b>\n <ul>\n <li><b>Path to save:</b> {{ storagePath }}</li>\n <li>\n <b>Resoluciones:</b>\n <span>{{ imgStorageSettings()?.cropSettings?.resolutions }}</span>\n </li>\n </ul>\n </p-message>\n\n <div class=\"setting-item\">\n <span class=\"setting-label\">Aspecto:</span>\n <p class=\"setting-value\">{{ imgStorageSettings()?.cropSettings?.aspectRatio }}</p>\n </div>\n\n @if (fileMetadata) {\n <div class=\"metadata-section\">\n <span class=\"metadata-item\">tipo: {{ fileMetadata.type }}</span>\n <span class=\"metadata-item\">tama\u00F1o: {{ fileMetadata.size }}</span>\n </div>\n }\n </div>\n <div class=\"col-12 md:col-6\">\n <div class=\"flex flex-column gap-2\">\n <div>\n <span>Nombre del archivo</span>\n <p-select\n [options]=\"aspectRatioOptions\"\n [ngModel]=\"ratioSelected\"\n (ngModelChange)=\"changeRatio($event)\"\n optionLabel=\"description\"\n placeholder=\"Select a ratio\">\n <ng-template pTemplate=\"selectedItem\" let-selectedOption>\n @if(selectedOption) {\n <div class=\"flex items-center gap-2\">\n <div [innerHTML]=\"selectedOption.icon | safeHtml\"></div>\n <div>{{ selectedOption.description }}</div>\n </div>\n }\n </ng-template>\n <ng-template let-ratio pTemplate=\"item\">\n <div class=\"flex items-center gap-2\">\n <div [innerHTML]=\"ratio.icon | safeHtml\"></div>\n <div>{{ ratio.description }}</div>\n </div>\n </ng-template>\n </p-select>\n </div>\n\n <div>\n <span>Nombre del archivo</span>\n <input\n pInputText\n [disabled]=\"imgStorageSettings()?.fileName\"\n [(ngModel)]=\"renameFile\"\n type=\"text\"\n placeholder=\"Rename File\"\n (ngModelChange)=\"reloadPath()\"\n class=\"rename-input\" />\n </div>\n\n <div>\n <span>Datos adicionales</span>\n <p-select\n [options]=\"MoodStateOptions\"\n [(ngModel)]=\"emotionSelected\"\n (ngModelChange)=\"addEmotion($event)\"\n optionLabel=\"label\"\n optionValue=\"value\"\n placeholder=\"Select an emotion\" />\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<!-- Image Cropper -->\n<hr />\n\n<div class=\"cropper-container-father\">\n <image-cropper\n [imageChangedEvent]=\"imageChangedEvent\"\n [maintainAspectRatio]=\"true\"\n [aspectRatio]=\"aspectRatioValue\"\n format=\"webp\"\n [resizeToWidth]=\"resizeToWidth\"\n (imageCropped)=\"onInnerImageCropped($event)\"\n (loadImageFailed)=\"loadImageFailed()\"\n (cropperReady)=\"cropperReady()\"\n [autoCrop]=\"false\">\n </image-cropper>\n</div>\n\n<!-- Dialog Footer -->\n<div class=\"p-dialog-footer\">\n <button pButton class=\"p-button-primary\" (click)=\"simpleCropAndUpload()\">Recortar y Subir</button>\n</div>\n}\n", styles: [":host{display:block}:host ::ng-deep .ngx-ic-overlay{width:100%!important}.upload-section{margin-bottom:1rem}.upload-section .file-input{display:none}.upload-section .upload-button{cursor:pointer}::ng-deep .cropper-dialog{max-width:90vw;width:800px}::ng-deep .cropper-dialog .p-dialog-content{padding:1.5rem}.settings-section{margin-bottom:1.5rem}.settings-section .grid .col-12{padding-top:0;padding-bottom:0}.settings-section .settings-header{color:var(--text-color-secondary);margin-bottom:1rem}.settings-section .settings-grid{display:grid;gap:1rem;margin-bottom:1.5rem}.settings-section .settings-grid .setting-item .setting-label{font-weight:600;color:var(--text-color);display:block;margin-bottom:.5rem}.settings-section .settings-grid .setting-item .setting-value{color:var(--text-color-secondary);margin:0}.metadata-section{display:flex;gap:1.5rem;margin-bottom:1rem}.metadata-section .metadata-item{color:var(--text-color-secondary)}.rename-section{margin-bottom:5px}.rename-section .rename-input{width:100%;padding:.5rem;border:1px solid var(--surface-border);border-radius:4px}.rename-section .rename-input:disabled{background-color:var(--surface-200);cursor:not-allowed}.cropper-container-father{display:flex;justify-content:center;align-items:center;height:65vh}.dialog-footer{display:flex;justify-content:flex-end;gap:1rem}.btn-crop{cursor:pointer;outline:0;display:inline-block;font-weight:400;line-height:1.5;text-align:center;background-color:transparent;border:1px solid transparent;padding:6px 12px;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;color:#0d6efd;border-color:#0d6efd}.btn-crop :hover{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.file-input{display:none}.btn-upload{cursor:pointer;outline:0;display:inline-block;font-weight:400;line-height:1.5;text-align:center;background-color:transparent;border:1px solid #0d6efd;padding:6px 12px;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;color:#0d6efd}.btn-upload:hover{color:#fff;background-color:#0d6efd}.modal{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;z-index:1000}.modal.show-modal{display:flex;align-items:center;justify-content:center}.modal .modal-content{background-color:#fff;border-radius:8px;width:90%;max-width:800px;max-height:90vh;overflow-y:auto;position:relative}.modal .modal-header{padding:1rem;border-bottom:1px solid #dee2e6;display:flex;justify-content:space-between;align-items:center}.modal .modal-header h3{margin:0}.modal .modal-header .close-button{background:none;border:none;font-size:1.5rem;cursor:pointer;padding:0;color:#6c757d}.modal .modal-header .close-button:hover{color:#343a40}.modal .modal-body{padding:1rem;height:100vh;display:flex;flex-direction:column}.modal .modal-footer{padding:1rem;border-top:1px solid #dee2e6;display:flex;justify-content:flex-end}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ImageCropperComponent, selector: "image-cropper", inputs: ["imageChangedEvent", "imageURL", "imageBase64", "imageFile", "imageAltText", "options", "cropperFrameAriaLabel", "output", "format", "autoCrop", "cropper", "transform", "maintainAspectRatio", "aspectRatio", "resetCropOnAspectRatioChange", "resizeToWidth", "resizeToHeight", "cropperMinWidth", "cropperMinHeight", "cropperMaxHeight", "cropperMaxWidth", "cropperStaticWidth", "cropperStaticHeight", "canvasRotation", "initialStepSize", "roundCropper", "onlyScaleDown", "imageQuality", "backgroundColor", "containWithinAspectRatio", "hideResizeSquares", "allowMoveImage", "checkImageType", "alignImage", "disabled", "hidden"], outputs: ["imageCropped", "startCropImage", "imageLoaded", "cropperReady", "loadImageFailed", "transformChange", "cropperChange"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i4.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: i5.Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant"], outputs: ["onClose"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i6.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i7.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: FieldsetModule }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] }); }
|
|
611
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: CropperComponentModal, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
612
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: CropperComponentModal, isStandalone: true, selector: "dc-cropper-modal", inputs: { imgStorageSettings: { classPropertyName: "imgStorageSettings", publicName: "imgStorageSettings", isSignal: true, isRequired: false, transformFunction: null }, buttonLabel: { classPropertyName: "buttonLabel", publicName: "buttonLabel", isSignal: true, isRequired: false, transformFunction: null }, currentStorage: { classPropertyName: "currentStorage", publicName: "currentStorage", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { imageUploaded: "imageUploaded", onImageCropped: "onImageCropped", onFileSelected: "onFileSelected" }, viewQueries: [{ propertyName: "imageCropper", first: true, predicate: ImageCropperComponent, descendants: true }], ngImport: i0, template: "<div class=\"upload-section\">\n <input type=\"file\" [id]=\"fileInputId\" class=\"file-input\" (change)=\"fileChangeEvent($event)\" />\n <label pButton [for]=\"fileInputId\" [pTooltip]=\"storagePath\" class=\"upload-button\">\n {{ buttonLabel() }}\n </label>\n</div>\n@if(displayDialog) {\n<!-- Cropper Dialog -->\n\n<p-dialog\n header=\"Recortar y subir imagen\"\n [maximizable]=\"true\"\n [(visible)]=\"displayDialog\"\n [modal]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n styleClass=\"cropper-dialog\">\n <!-- Image Settings Section -->\n <div class=\"settings-section\">\n @if(!imgStorageSettings().path) {\n <p-message severity=\"warn\">Developer Note: make sure you have a path to save the image pass object imgStorageSettings</p-message>\n } @if(currentStorage?.url) {\n <p-message severity=\"warn\" variant=\"outlined\">\n <div>\n <span class=\"setting-label\">Image will be replaced:</span>\n <img width=\"100\" height=\"Auto\" [src]=\"currentStorage?.url\" />\n </div>\n </p-message>\n }\n\n <div class=\"grid\">\n <div class=\"col-12 md:col-6\">\n <p-message>\n <b>Estas opciones estan preconfiguradas y no se pueden cambiar</b>\n <ul>\n <li><b>Path to save:</b> {{ storagePath }}</li>\n <li>\n <b>Resoluciones:</b>\n <span>{{ imgStorageSettings()?.cropSettings?.resolutions }}</span>\n </li>\n </ul>\n </p-message>\n\n <div class=\"setting-item\">\n <span class=\"setting-label\">Aspecto:</span>\n <p class=\"setting-value\">{{ imgStorageSettings()?.cropSettings?.aspectRatio }}</p>\n </div>\n\n @if (fileMetadata) {\n <div class=\"metadata-section\">\n <span class=\"metadata-item\">tipo: {{ fileMetadata.type }}</span>\n <span class=\"metadata-item\">tama\u00F1o: {{ fileMetadata.size }}</span>\n </div>\n }\n </div>\n <div class=\"col-12 md:col-6\">\n <div class=\"flex flex-column gap-2\">\n <div>\n <span>Nombre del archivo</span>\n <p-select\n [options]=\"aspectRatioOptions\"\n [ngModel]=\"ratioSelected\"\n (ngModelChange)=\"changeRatio($event)\"\n optionLabel=\"description\"\n placeholder=\"Select a ratio\">\n <ng-template pTemplate=\"selectedItem\" let-selectedOption>\n @if(selectedOption) {\n <div class=\"flex items-center gap-2\">\n <div [innerHTML]=\"selectedOption.icon | safeHtml\"></div>\n <div>{{ selectedOption.description }}</div>\n </div>\n }\n </ng-template>\n <ng-template let-ratio pTemplate=\"item\">\n <div class=\"flex items-center gap-2\">\n <div [innerHTML]=\"ratio.icon | safeHtml\"></div>\n <div>{{ ratio.description }}</div>\n </div>\n </ng-template>\n </p-select>\n </div>\n\n <div>\n <span>Nombre del archivo</span>\n <input\n pInputText\n [disabled]=\"imgStorageSettings()?.fileName\"\n [(ngModel)]=\"renameFile\"\n type=\"text\"\n placeholder=\"Rename File\"\n (ngModelChange)=\"reloadPath()\"\n class=\"rename-input\" />\n </div>\n\n <div>\n <span>Datos adicionales</span>\n <p-select\n [options]=\"MoodStateOptions\"\n [(ngModel)]=\"emotionSelected\"\n (ngModelChange)=\"addEmotion($event)\"\n optionLabel=\"label\"\n optionValue=\"value\"\n placeholder=\"Select an emotion\" />\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Image Cropper -->\n\n <hr />\n\n <div class=\"cropper-container-father\">\n <image-cropper\n [imageChangedEvent]=\"imageChangedEvent\"\n [maintainAspectRatio]=\"true\"\n [aspectRatio]=\"aspectRatioValue\"\n format=\"webp\"\n [resizeToWidth]=\"resizeToWidth\"\n (imageCropped)=\"onInnerImageCropped($event)\"\n (loadImageFailed)=\"loadImageFailed()\"\n (cropperReady)=\"cropperReady()\"\n [autoCrop]=\"false\">\n </image-cropper>\n </div>\n <!-- Dialog Footer -->\n <ng-template pTemplate=\"footer\">\n <div class=\"dialog-footer\">\n <button pButton class=\"p-button-primary\" (click)=\"simpleCropAndUpload()\"> Recortar y Subir </button>\n </div>\n </ng-template>\n</p-dialog>\n}\n", styles: [":host{display:block}:host ::ng-deep .ngx-ic-overlay{width:100%!important}.upload-section{margin-bottom:1rem}.upload-section .file-input{display:none}.upload-section .upload-button{cursor:pointer}::ng-deep .cropper-dialog{max-width:90vw;width:800px}::ng-deep .cropper-dialog .p-dialog-content{padding:1.5rem}.settings-section{margin-bottom:1.5rem}.settings-section .grid .col-12{padding-top:0;padding-bottom:0}.settings-section .settings-header{color:var(--text-color-secondary);margin-bottom:1rem}.settings-section .settings-grid{display:grid;gap:1rem;margin-bottom:1.5rem}.settings-section .settings-grid .setting-item .setting-label{font-weight:600;color:var(--text-color);display:block;margin-bottom:.5rem}.settings-section .settings-grid .setting-item .setting-value{color:var(--text-color-secondary);margin:0}.metadata-section{display:flex;gap:1.5rem;margin-bottom:1rem}.metadata-section .metadata-item{color:var(--text-color-secondary)}.rename-section{margin-bottom:5px}.rename-section .rename-input{width:100%;padding:.5rem;border:1px solid var(--surface-border);border-radius:4px}.rename-section .rename-input:disabled{background-color:var(--surface-200);cursor:not-allowed}.cropper-container-father{display:flex;justify-content:center;align-items:center;height:65vh}.dialog-footer{display:flex;justify-content:flex-end;gap:1rem}.btn-crop{cursor:pointer;outline:0;display:inline-block;font-weight:400;line-height:1.5;text-align:center;background-color:transparent;border:1px solid transparent;padding:6px 12px;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;color:#0d6efd;border-color:#0d6efd}.btn-crop :hover{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.file-input{display:none}.btn-upload{cursor:pointer;outline:0;display:inline-block;font-weight:400;line-height:1.5;text-align:center;background-color:transparent;border:1px solid #0d6efd;padding:6px 12px;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;color:#0d6efd}.btn-upload:hover{color:#fff;background-color:#0d6efd}.modal{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;z-index:1000}.modal.show-modal{display:flex;align-items:center;justify-content:center}.modal .modal-content{background-color:#fff;border-radius:8px;width:90%;max-width:800px;max-height:90vh;overflow-y:auto;position:relative}.modal .modal-header{padding:1rem;border-bottom:1px solid #dee2e6;display:flex;justify-content:space-between;align-items:center}.modal .modal-header h3{margin:0}.modal .modal-header .close-button{background:none;border:none;font-size:1.5rem;cursor:pointer;padding:0;color:#6c757d}.modal .modal-header .close-button:hover{color:#343a40}.modal .modal-body{padding:1rem;height:100vh;display:flex;flex-direction:column}.modal .modal-footer{padding:1rem;border-top:1px solid #dee2e6;display:flex;justify-content:flex-end}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ImageCropperComponent, selector: "image-cropper", inputs: ["imageChangedEvent", "imageURL", "imageBase64", "imageFile", "imageAltText", "options", "cropperFrameAriaLabel", "output", "format", "autoCrop", "cropper", "transform", "maintainAspectRatio", "aspectRatio", "resetCropOnAspectRatioChange", "resizeToWidth", "resizeToHeight", "cropperMinWidth", "cropperMinHeight", "cropperMaxHeight", "cropperMaxWidth", "cropperStaticWidth", "cropperStaticHeight", "canvasRotation", "initialStepSize", "roundCropper", "onlyScaleDown", "imageQuality", "backgroundColor", "containWithinAspectRatio", "hideResizeSquares", "allowMoveImage", "checkImageType", "alignImage", "disabled", "hidden"], outputs: ["imageCropped", "startCropImage", "imageLoaded", "cropperReady", "loadImageFailed", "transformChange", "cropperChange"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i4.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: i6.Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant", "motionOptions"], outputs: ["onClose"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i7.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i8.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] }); }
|
|
624
613
|
}
|
|
625
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
614
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: CropperComponentModal, decorators: [{
|
|
626
615
|
type: Component,
|
|
627
|
-
args: [{ selector: 'dc-cropper-modal', standalone: true, imports: [
|
|
628
|
-
|
|
629
|
-
ImageCropperComponent,
|
|
630
|
-
ButtonModule,
|
|
631
|
-
DialogModule,
|
|
632
|
-
TooltipModule,
|
|
633
|
-
MessageModule,
|
|
634
|
-
SelectModule,
|
|
635
|
-
InputTextModule,
|
|
636
|
-
SafeHtmlPipe,
|
|
637
|
-
FieldsetModule,
|
|
638
|
-
DynamicDialogModule,
|
|
639
|
-
], providers: [DialogService], template: "<!-- src/app/components/cropper-modal/cropper-modal.component.html -->\n@if(!config?.data) {\n<div class=\"upload-section\">\n <input type=\"file\" [id]=\"fileInputId\" class=\"file-input\" (change)=\"fileChangeEvent($event)\" />\n <label pButton [for]=\"fileInputId\" [pTooltip]=\"storagePath\" class=\"upload-button\">\n {{ buttonLabel() }}\n </label>\n</div>\n} @else {\n<!-- Image Settings Section -->\n<div class=\"settings-section\">\n @if(!imgStorageSettings().path) {\n <p-message severity=\"warn\">Developer Note: make sure you have a path to save the image pass object imgStorageSettings</p-message>\n } @if(currentStorage?.url) {\n <p-message severity=\"warn\" variant=\"outlined\">\n <div>\n <span class=\"setting-label\">Image will be replaced:</span>\n <img width=\"100\" height=\"Auto\" [src]=\"currentStorage?.url\" />\n </div>\n </p-message>\n }\n\n <div class=\"grid\">\n <div class=\"col-12 md:col-6\">\n <p-message>\n <b>Estas opciones estan preconfiguradas y no se pueden cambiar</b>\n <ul>\n <li><b>Path to save:</b> {{ storagePath }}</li>\n <li>\n <b>Resoluciones:</b>\n <span>{{ imgStorageSettings()?.cropSettings?.resolutions }}</span>\n </li>\n </ul>\n </p-message>\n\n <div class=\"setting-item\">\n <span class=\"setting-label\">Aspecto:</span>\n <p class=\"setting-value\">{{ imgStorageSettings()?.cropSettings?.aspectRatio }}</p>\n </div>\n\n @if (fileMetadata) {\n <div class=\"metadata-section\">\n <span class=\"metadata-item\">tipo: {{ fileMetadata.type }}</span>\n <span class=\"metadata-item\">tama\u00F1o: {{ fileMetadata.size }}</span>\n </div>\n }\n </div>\n <div class=\"col-12 md:col-6\">\n <div class=\"flex flex-column gap-2\">\n <div>\n <span>Nombre del archivo</span>\n <p-select\n [options]=\"aspectRatioOptions\"\n [ngModel]=\"ratioSelected\"\n (ngModelChange)=\"changeRatio($event)\"\n optionLabel=\"description\"\n placeholder=\"Select a ratio\">\n <ng-template pTemplate=\"selectedItem\" let-selectedOption>\n @if(selectedOption) {\n <div class=\"flex items-center gap-2\">\n <div [innerHTML]=\"selectedOption.icon | safeHtml\"></div>\n <div>{{ selectedOption.description }}</div>\n </div>\n }\n </ng-template>\n <ng-template let-ratio pTemplate=\"item\">\n <div class=\"flex items-center gap-2\">\n <div [innerHTML]=\"ratio.icon | safeHtml\"></div>\n <div>{{ ratio.description }}</div>\n </div>\n </ng-template>\n </p-select>\n </div>\n\n <div>\n <span>Nombre del archivo</span>\n <input\n pInputText\n [disabled]=\"imgStorageSettings()?.fileName\"\n [(ngModel)]=\"renameFile\"\n type=\"text\"\n placeholder=\"Rename File\"\n (ngModelChange)=\"reloadPath()\"\n class=\"rename-input\" />\n </div>\n\n <div>\n <span>Datos adicionales</span>\n <p-select\n [options]=\"MoodStateOptions\"\n [(ngModel)]=\"emotionSelected\"\n (ngModelChange)=\"addEmotion($event)\"\n optionLabel=\"label\"\n optionValue=\"value\"\n placeholder=\"Select an emotion\" />\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<!-- Image Cropper -->\n<hr />\n\n<div class=\"cropper-container-father\">\n <image-cropper\n [imageChangedEvent]=\"imageChangedEvent\"\n [maintainAspectRatio]=\"true\"\n [aspectRatio]=\"aspectRatioValue\"\n format=\"webp\"\n [resizeToWidth]=\"resizeToWidth\"\n (imageCropped)=\"onInnerImageCropped($event)\"\n (loadImageFailed)=\"loadImageFailed()\"\n (cropperReady)=\"cropperReady()\"\n [autoCrop]=\"false\">\n </image-cropper>\n</div>\n\n<!-- Dialog Footer -->\n<div class=\"p-dialog-footer\">\n <button pButton class=\"p-button-primary\" (click)=\"simpleCropAndUpload()\">Recortar y Subir</button>\n</div>\n}\n", styles: [":host{display:block}:host ::ng-deep .ngx-ic-overlay{width:100%!important}.upload-section{margin-bottom:1rem}.upload-section .file-input{display:none}.upload-section .upload-button{cursor:pointer}::ng-deep .cropper-dialog{max-width:90vw;width:800px}::ng-deep .cropper-dialog .p-dialog-content{padding:1.5rem}.settings-section{margin-bottom:1.5rem}.settings-section .grid .col-12{padding-top:0;padding-bottom:0}.settings-section .settings-header{color:var(--text-color-secondary);margin-bottom:1rem}.settings-section .settings-grid{display:grid;gap:1rem;margin-bottom:1.5rem}.settings-section .settings-grid .setting-item .setting-label{font-weight:600;color:var(--text-color);display:block;margin-bottom:.5rem}.settings-section .settings-grid .setting-item .setting-value{color:var(--text-color-secondary);margin:0}.metadata-section{display:flex;gap:1.5rem;margin-bottom:1rem}.metadata-section .metadata-item{color:var(--text-color-secondary)}.rename-section{margin-bottom:5px}.rename-section .rename-input{width:100%;padding:.5rem;border:1px solid var(--surface-border);border-radius:4px}.rename-section .rename-input:disabled{background-color:var(--surface-200);cursor:not-allowed}.cropper-container-father{display:flex;justify-content:center;align-items:center;height:65vh}.dialog-footer{display:flex;justify-content:flex-end;gap:1rem}.btn-crop{cursor:pointer;outline:0;display:inline-block;font-weight:400;line-height:1.5;text-align:center;background-color:transparent;border:1px solid transparent;padding:6px 12px;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;color:#0d6efd;border-color:#0d6efd}.btn-crop :hover{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.file-input{display:none}.btn-upload{cursor:pointer;outline:0;display:inline-block;font-weight:400;line-height:1.5;text-align:center;background-color:transparent;border:1px solid #0d6efd;padding:6px 12px;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;color:#0d6efd}.btn-upload:hover{color:#fff;background-color:#0d6efd}.modal{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;z-index:1000}.modal.show-modal{display:flex;align-items:center;justify-content:center}.modal .modal-content{background-color:#fff;border-radius:8px;width:90%;max-width:800px;max-height:90vh;overflow-y:auto;position:relative}.modal .modal-header{padding:1rem;border-bottom:1px solid #dee2e6;display:flex;justify-content:space-between;align-items:center}.modal .modal-header h3{margin:0}.modal .modal-header .close-button{background:none;border:none;font-size:1.5rem;cursor:pointer;padding:0;color:#6c757d}.modal .modal-header .close-button:hover{color:#343a40}.modal .modal-body{padding:1rem;height:100vh;display:flex;flex-direction:column}.modal .modal-footer{padding:1rem;border-top:1px solid #dee2e6;display:flex;justify-content:flex-end}\n"] }]
|
|
640
|
-
}], ctorParameters: () => [], propDecorators: { currentStorage: [{
|
|
616
|
+
args: [{ selector: 'dc-cropper-modal', standalone: true, imports: [FormsModule, ImageCropperComponent, ButtonModule, DialogModule, TooltipModule, MessageModule, SelectModule, InputTextModule, SafeHtmlPipe], template: "<div class=\"upload-section\">\n <input type=\"file\" [id]=\"fileInputId\" class=\"file-input\" (change)=\"fileChangeEvent($event)\" />\n <label pButton [for]=\"fileInputId\" [pTooltip]=\"storagePath\" class=\"upload-button\">\n {{ buttonLabel() }}\n </label>\n</div>\n@if(displayDialog) {\n<!-- Cropper Dialog -->\n\n<p-dialog\n header=\"Recortar y subir imagen\"\n [maximizable]=\"true\"\n [(visible)]=\"displayDialog\"\n [modal]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n styleClass=\"cropper-dialog\">\n <!-- Image Settings Section -->\n <div class=\"settings-section\">\n @if(!imgStorageSettings().path) {\n <p-message severity=\"warn\">Developer Note: make sure you have a path to save the image pass object imgStorageSettings</p-message>\n } @if(currentStorage?.url) {\n <p-message severity=\"warn\" variant=\"outlined\">\n <div>\n <span class=\"setting-label\">Image will be replaced:</span>\n <img width=\"100\" height=\"Auto\" [src]=\"currentStorage?.url\" />\n </div>\n </p-message>\n }\n\n <div class=\"grid\">\n <div class=\"col-12 md:col-6\">\n <p-message>\n <b>Estas opciones estan preconfiguradas y no se pueden cambiar</b>\n <ul>\n <li><b>Path to save:</b> {{ storagePath }}</li>\n <li>\n <b>Resoluciones:</b>\n <span>{{ imgStorageSettings()?.cropSettings?.resolutions }}</span>\n </li>\n </ul>\n </p-message>\n\n <div class=\"setting-item\">\n <span class=\"setting-label\">Aspecto:</span>\n <p class=\"setting-value\">{{ imgStorageSettings()?.cropSettings?.aspectRatio }}</p>\n </div>\n\n @if (fileMetadata) {\n <div class=\"metadata-section\">\n <span class=\"metadata-item\">tipo: {{ fileMetadata.type }}</span>\n <span class=\"metadata-item\">tama\u00F1o: {{ fileMetadata.size }}</span>\n </div>\n }\n </div>\n <div class=\"col-12 md:col-6\">\n <div class=\"flex flex-column gap-2\">\n <div>\n <span>Nombre del archivo</span>\n <p-select\n [options]=\"aspectRatioOptions\"\n [ngModel]=\"ratioSelected\"\n (ngModelChange)=\"changeRatio($event)\"\n optionLabel=\"description\"\n placeholder=\"Select a ratio\">\n <ng-template pTemplate=\"selectedItem\" let-selectedOption>\n @if(selectedOption) {\n <div class=\"flex items-center gap-2\">\n <div [innerHTML]=\"selectedOption.icon | safeHtml\"></div>\n <div>{{ selectedOption.description }}</div>\n </div>\n }\n </ng-template>\n <ng-template let-ratio pTemplate=\"item\">\n <div class=\"flex items-center gap-2\">\n <div [innerHTML]=\"ratio.icon | safeHtml\"></div>\n <div>{{ ratio.description }}</div>\n </div>\n </ng-template>\n </p-select>\n </div>\n\n <div>\n <span>Nombre del archivo</span>\n <input\n pInputText\n [disabled]=\"imgStorageSettings()?.fileName\"\n [(ngModel)]=\"renameFile\"\n type=\"text\"\n placeholder=\"Rename File\"\n (ngModelChange)=\"reloadPath()\"\n class=\"rename-input\" />\n </div>\n\n <div>\n <span>Datos adicionales</span>\n <p-select\n [options]=\"MoodStateOptions\"\n [(ngModel)]=\"emotionSelected\"\n (ngModelChange)=\"addEmotion($event)\"\n optionLabel=\"label\"\n optionValue=\"value\"\n placeholder=\"Select an emotion\" />\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Image Cropper -->\n\n <hr />\n\n <div class=\"cropper-container-father\">\n <image-cropper\n [imageChangedEvent]=\"imageChangedEvent\"\n [maintainAspectRatio]=\"true\"\n [aspectRatio]=\"aspectRatioValue\"\n format=\"webp\"\n [resizeToWidth]=\"resizeToWidth\"\n (imageCropped)=\"onInnerImageCropped($event)\"\n (loadImageFailed)=\"loadImageFailed()\"\n (cropperReady)=\"cropperReady()\"\n [autoCrop]=\"false\">\n </image-cropper>\n </div>\n <!-- Dialog Footer -->\n <ng-template pTemplate=\"footer\">\n <div class=\"dialog-footer\">\n <button pButton class=\"p-button-primary\" (click)=\"simpleCropAndUpload()\"> Recortar y Subir </button>\n </div>\n </ng-template>\n</p-dialog>\n}\n", styles: [":host{display:block}:host ::ng-deep .ngx-ic-overlay{width:100%!important}.upload-section{margin-bottom:1rem}.upload-section .file-input{display:none}.upload-section .upload-button{cursor:pointer}::ng-deep .cropper-dialog{max-width:90vw;width:800px}::ng-deep .cropper-dialog .p-dialog-content{padding:1.5rem}.settings-section{margin-bottom:1.5rem}.settings-section .grid .col-12{padding-top:0;padding-bottom:0}.settings-section .settings-header{color:var(--text-color-secondary);margin-bottom:1rem}.settings-section .settings-grid{display:grid;gap:1rem;margin-bottom:1.5rem}.settings-section .settings-grid .setting-item .setting-label{font-weight:600;color:var(--text-color);display:block;margin-bottom:.5rem}.settings-section .settings-grid .setting-item .setting-value{color:var(--text-color-secondary);margin:0}.metadata-section{display:flex;gap:1.5rem;margin-bottom:1rem}.metadata-section .metadata-item{color:var(--text-color-secondary)}.rename-section{margin-bottom:5px}.rename-section .rename-input{width:100%;padding:.5rem;border:1px solid var(--surface-border);border-radius:4px}.rename-section .rename-input:disabled{background-color:var(--surface-200);cursor:not-allowed}.cropper-container-father{display:flex;justify-content:center;align-items:center;height:65vh}.dialog-footer{display:flex;justify-content:flex-end;gap:1rem}.btn-crop{cursor:pointer;outline:0;display:inline-block;font-weight:400;line-height:1.5;text-align:center;background-color:transparent;border:1px solid transparent;padding:6px 12px;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;color:#0d6efd;border-color:#0d6efd}.btn-crop :hover{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.file-input{display:none}.btn-upload{cursor:pointer;outline:0;display:inline-block;font-weight:400;line-height:1.5;text-align:center;background-color:transparent;border:1px solid #0d6efd;padding:6px 12px;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;color:#0d6efd}.btn-upload:hover{color:#fff;background-color:#0d6efd}.modal{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;z-index:1000}.modal.show-modal{display:flex;align-items:center;justify-content:center}.modal .modal-content{background-color:#fff;border-radius:8px;width:90%;max-width:800px;max-height:90vh;overflow-y:auto;position:relative}.modal .modal-header{padding:1rem;border-bottom:1px solid #dee2e6;display:flex;justify-content:space-between;align-items:center}.modal .modal-header h3{margin:0}.modal .modal-header .close-button{background:none;border:none;font-size:1.5rem;cursor:pointer;padding:0;color:#6c757d}.modal .modal-header .close-button:hover{color:#343a40}.modal .modal-body{padding:1rem;height:100vh;display:flex;flex-direction:column}.modal .modal-footer{padding:1rem;border-top:1px solid #dee2e6;display:flex;justify-content:flex-end}\n"] }]
|
|
617
|
+
}], ctorParameters: () => [], propDecorators: { imgStorageSettings: [{ type: i0.Input, args: [{ isSignal: true, alias: "imgStorageSettings", required: false }] }], buttonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonLabel", required: false }] }], currentStorage: [{
|
|
641
618
|
type: Input
|
|
642
|
-
}], imageCropper: [{
|
|
619
|
+
}], imageUploaded: [{ type: i0.Output, args: ["imageUploaded"] }], onImageCropped: [{ type: i0.Output, args: ["onImageCropped"] }], onFileSelected: [{ type: i0.Output, args: ["onFileSelected"] }], imageCropper: [{
|
|
643
620
|
type: ViewChild,
|
|
644
621
|
args: [ImageCropperComponent]
|
|
645
622
|
}] } });
|
|
@@ -717,13 +694,13 @@ class ImageStoragePreviewComponent {
|
|
|
717
694
|
selectImage(image) {
|
|
718
695
|
this.imageSelected.emit(image);
|
|
719
696
|
}
|
|
720
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
721
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
697
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ImageStoragePreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
698
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: ImageStoragePreviewComponent, isStandalone: true, selector: "dc-image-storage-preview", outputs: { imageSelected: "imageSelected" }, ngImport: i0, template: "<div class=\"image-storage-preview-container\">\n <div class=\"header\">\n <h2>Storage Images</h2>\n <button class=\"refresh-btn\" (click)=\"refreshImages()\" [disabled]=\"loading$ | async\">\n @if (!(loading$ | async)) {\n <span>Refresh</span>\n }\n @if (loading$ | async) {\n <span>Loading...</span>\n }\n </button>\n </div>\n\n @if (loading$ | async) {\n <div class=\"loading-container\">\n <div class=\"spinner\"></div>\n <p>Loading images...</p>\n </div>\n }\n\n @if (error$ | async) {\n <div class=\"error-container\">\n <p class=\"error-message\">{{ error$ | async }}</p>\n <button (click)=\"refreshImages()\">Try Again</button>\n </div>\n }\n\n @if (!(loading$ | async) && !(error$ | async)) {\n <div class=\"images-grid\">\n @if ((images$ | async)?.length) {\n @for (image of images$ | async; track image) {\n <div class=\"image-card\">\n <div class=\"image-container\">\n <img [src]=\"image.url\" [alt]=\"image.name || 'Storage image'\" loading=\"lazy\" />\n </div>\n <div class=\"image-info\">\n <p class=\"image-name\" [title]=\"image.name\">{{ image.name }}</p>\n <div class=\"image-actions\">\n <a [href]=\"image.url\" target=\"_blank\" class=\"action-btn\">View</a>\n <button (click)=\"selectImage(image)\" class=\"action-btn\">Select</button>\n </div>\n </div>\n </div>\n }\n } @else {\n <div class=\"no-images\">\n <p>No images found in the storage path: {{ storagePath }}</p>\n </div>\n }\n <dc-cropper-modal [imgStorageSettings]=\"imgStorageSettings\"></dc-cropper-modal>\n </div>\n }\n</div>\n", styles: [".image-storage-preview-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;padding:20px;max-width:1200px;margin:0 auto}.header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.header h2{margin:0;color:#333}.refresh-btn{background-color:#4285f4;color:#fff;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-size:14px;transition:background-color .2s}.refresh-btn:hover{background-color:#3367d6}.refresh-btn:disabled{background-color:#a9a9a9;cursor:not-allowed}.loading-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 0}.spinner{border:4px solid rgba(0,0,0,.1);border-radius:50%;border-top:4px solid #4285f4;width:30px;height:30px;animation:spin 1s linear infinite;margin-bottom:15px}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.error-container{background-color:#ffebee;border:1px solid #ffcdd2;border-radius:4px;padding:16px;margin:20px 0;text-align:center}.error-message{color:#d32f2f;margin-bottom:10px}.error-container button{background-color:#d32f2f;color:#fff;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-size:14px}.images-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:20px}.image-card{border-radius:8px;overflow:hidden;box-shadow:0 2px 10px #0000001a;transition:transform .2s,box-shadow .2s;background-color:#fff}.image-card:hover{transform:translateY(-5px);box-shadow:0 5px 15px #00000026}.image-container{height:200px;overflow:hidden;position:relative;background-color:#f5f5f5}.image-container img{width:100%;height:100%;object-fit:cover;transition:transform .3s}.image-card:hover .image-container img{transform:scale(1.05)}.image-info{padding:15px}.image-name{margin:0 0 10px;font-size:14px;font-weight:500;color:#333;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.image-actions{display:flex;justify-content:flex-end}.action-btn{background-color:#4285f4;color:#fff;text-decoration:none;border-radius:4px;padding:6px 12px;font-size:12px;transition:background-color .2s}.action-btn:hover{background-color:#3367d6}.no-images{grid-column:1 / -1;text-align:center;padding:40px 0;color:#757575;background-color:#f5f5f5;border-radius:8px}\n"], dependencies: [{ kind: "component", type: CropperComponentModal, selector: "dc-cropper-modal", inputs: ["imgStorageSettings", "buttonLabel", "currentStorage"], outputs: ["imageUploaded", "onImageCropped", "onFileSelected"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] }); }
|
|
722
699
|
}
|
|
723
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
700
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ImageStoragePreviewComponent, decorators: [{
|
|
724
701
|
type: Component,
|
|
725
702
|
args: [{ selector: 'dc-image-storage-preview', standalone: true, imports: [AsyncPipe, CropperComponentModal], template: "<div class=\"image-storage-preview-container\">\n <div class=\"header\">\n <h2>Storage Images</h2>\n <button class=\"refresh-btn\" (click)=\"refreshImages()\" [disabled]=\"loading$ | async\">\n @if (!(loading$ | async)) {\n <span>Refresh</span>\n }\n @if (loading$ | async) {\n <span>Loading...</span>\n }\n </button>\n </div>\n\n @if (loading$ | async) {\n <div class=\"loading-container\">\n <div class=\"spinner\"></div>\n <p>Loading images...</p>\n </div>\n }\n\n @if (error$ | async) {\n <div class=\"error-container\">\n <p class=\"error-message\">{{ error$ | async }}</p>\n <button (click)=\"refreshImages()\">Try Again</button>\n </div>\n }\n\n @if (!(loading$ | async) && !(error$ | async)) {\n <div class=\"images-grid\">\n @if ((images$ | async)?.length) {\n @for (image of images$ | async; track image) {\n <div class=\"image-card\">\n <div class=\"image-container\">\n <img [src]=\"image.url\" [alt]=\"image.name || 'Storage image'\" loading=\"lazy\" />\n </div>\n <div class=\"image-info\">\n <p class=\"image-name\" [title]=\"image.name\">{{ image.name }}</p>\n <div class=\"image-actions\">\n <a [href]=\"image.url\" target=\"_blank\" class=\"action-btn\">View</a>\n <button (click)=\"selectImage(image)\" class=\"action-btn\">Select</button>\n </div>\n </div>\n </div>\n }\n } @else {\n <div class=\"no-images\">\n <p>No images found in the storage path: {{ storagePath }}</p>\n </div>\n }\n <dc-cropper-modal [imgStorageSettings]=\"imgStorageSettings\"></dc-cropper-modal>\n </div>\n }\n</div>\n", styles: [".image-storage-preview-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;padding:20px;max-width:1200px;margin:0 auto}.header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.header h2{margin:0;color:#333}.refresh-btn{background-color:#4285f4;color:#fff;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-size:14px;transition:background-color .2s}.refresh-btn:hover{background-color:#3367d6}.refresh-btn:disabled{background-color:#a9a9a9;cursor:not-allowed}.loading-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 0}.spinner{border:4px solid rgba(0,0,0,.1);border-radius:50%;border-top:4px solid #4285f4;width:30px;height:30px;animation:spin 1s linear infinite;margin-bottom:15px}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.error-container{background-color:#ffebee;border:1px solid #ffcdd2;border-radius:4px;padding:16px;margin:20px 0;text-align:center}.error-message{color:#d32f2f;margin-bottom:10px}.error-container button{background-color:#d32f2f;color:#fff;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-size:14px}.images-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:20px}.image-card{border-radius:8px;overflow:hidden;box-shadow:0 2px 10px #0000001a;transition:transform .2s,box-shadow .2s;background-color:#fff}.image-card:hover{transform:translateY(-5px);box-shadow:0 5px 15px #00000026}.image-container{height:200px;overflow:hidden;position:relative;background-color:#f5f5f5}.image-container img{width:100%;height:100%;object-fit:cover;transition:transform .3s}.image-card:hover .image-container img{transform:scale(1.05)}.image-info{padding:15px}.image-name{margin:0 0 10px;font-size:14px;font-weight:500;color:#333;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.image-actions{display:flex;justify-content:flex-end}.action-btn{background-color:#4285f4;color:#fff;text-decoration:none;border-radius:4px;padding:6px 12px;font-size:12px;transition:background-color .2s}.action-btn:hover{background-color:#3367d6}.no-images{grid-column:1 / -1;text-align:center;padding:40px 0;color:#757575;background-color:#f5f5f5;border-radius:8px}\n"] }]
|
|
726
|
-
}], ctorParameters: () => [] });
|
|
703
|
+
}], ctorParameters: () => [], propDecorators: { imageSelected: [{ type: i0.Output, args: ["imageSelected"] }] } });
|
|
727
704
|
|
|
728
705
|
class SimpleUploaderComponent {
|
|
729
706
|
constructor() {
|
|
@@ -794,13 +771,13 @@ class SimpleUploaderComponent {
|
|
|
794
771
|
}
|
|
795
772
|
}
|
|
796
773
|
}
|
|
797
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
798
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
774
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: SimpleUploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
775
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: SimpleUploaderComponent, isStandalone: true, selector: "dc-simple-uploader", inputs: { storagePath: { classPropertyName: "storagePath", publicName: "storagePath", isSignal: true, isRequired: true, transformFunction: null }, buttonLabel: { classPropertyName: "buttonLabel", publicName: "buttonLabel", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, metadata: { classPropertyName: "metadata", publicName: "metadata", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fileUploaded: "fileUploaded", uploadError: "uploadError" }, ngImport: i0, template: "<p-button\n size=\"large\"\n [label]=\"buttonLabel()\"\n (click)=\"openDialog()\"\n [loading]=\"isLoading()\"\n [disabled]=\"disabled() || isLoading()\"\n pTooltip=\"Upload a file with metadata\"></p-button>\n\n@if(displayDialog()){\n<p-dialog\n header=\"Upload File\"\n [(visible)]=\"displayDialog\"\n [modal]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n [contentStyle]=\"{ width: '50vw', height: '50vh' }\">\n <div class=\"upload-dialog\">\n @if(!fileSelected()){\n <div class=\"file-input-container\">\n <input #fileInput type=\"file\" [id]=\"fileInputId\" (change)=\"onFileSelected($event)\" [accept]=\"accept()\" style=\"display: none\" />\n <p-button label=\"Select File\" (click)=\"triggerFileInputClick(fileInput)\"></p-button>\n </div>\n } @else {\n <div class=\"file-details\">\n <p>File: {{ fileSelected()?.name }}</p>\n <p>Size: {{ fileSelected()?.size }} bytes</p>\n </div>\n\n <div class=\"metadata-container\">\n <h5>Metadata</h5>\n <div class=\"p-fluid\">\n @for (key of objectKeys(metadata()); track key) {\n <div class=\"p-field\">\n <label [for]=\"key\">{{ key }}</label>\n <input pInputText [id]=\"key\" [(ngModel)]=\"metadataInput[key]\" />\n </div>\n }\n\n <div class=\"p-field\">\n <label for=\"emotion\">Emotion</label>\n <br />\n <p-select [options]=\"MoodStateOptions\" [(ngModel)]=\"moodSelected\" optionLabel=\"label\" optionValue=\"value\" placeholder=\"Select an emotion\"></p-select>\n </div>\n <div class=\"p-field\">\n <label for=\"emotion\">Event</label>\n <br />\n <p-select\n [options]=\"CharacterEventActions\"\n [(ngModel)]=\"eventSelected\"\n optionLabel=\"label\"\n optionValue=\"value\"\n placeholder=\"Select an event\"></p-select>\n </div>\n </div>\n </div>\n }\n </div>\n\n <ng-template pTemplate=\"footer\">\n <div class=\"dialog-footer\">\n <p-button label=\"Cancel\" styleClass=\"p-button-secondary\" (click)=\"displayDialog.set(false)\"></p-button>\n <p-button label=\"Upload\" (click)=\"uploadFile()\" [disabled]=\"!fileSelected() || isLoading()\"></p-button>\n </div>\n </ng-template>\n</p-dialog>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i4.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i8.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i7.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }] }); }
|
|
799
776
|
}
|
|
800
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
777
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: SimpleUploaderComponent, decorators: [{
|
|
801
778
|
type: Component,
|
|
802
779
|
args: [{ selector: 'dc-simple-uploader', standalone: true, imports: [CommonModule, FormsModule, ButtonModule, TooltipModule, DialogModule, InputTextModule, SelectModule], template: "<p-button\n size=\"large\"\n [label]=\"buttonLabel()\"\n (click)=\"openDialog()\"\n [loading]=\"isLoading()\"\n [disabled]=\"disabled() || isLoading()\"\n pTooltip=\"Upload a file with metadata\"></p-button>\n\n@if(displayDialog()){\n<p-dialog\n header=\"Upload File\"\n [(visible)]=\"displayDialog\"\n [modal]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n [contentStyle]=\"{ width: '50vw', height: '50vh' }\">\n <div class=\"upload-dialog\">\n @if(!fileSelected()){\n <div class=\"file-input-container\">\n <input #fileInput type=\"file\" [id]=\"fileInputId\" (change)=\"onFileSelected($event)\" [accept]=\"accept()\" style=\"display: none\" />\n <p-button label=\"Select File\" (click)=\"triggerFileInputClick(fileInput)\"></p-button>\n </div>\n } @else {\n <div class=\"file-details\">\n <p>File: {{ fileSelected()?.name }}</p>\n <p>Size: {{ fileSelected()?.size }} bytes</p>\n </div>\n\n <div class=\"metadata-container\">\n <h5>Metadata</h5>\n <div class=\"p-fluid\">\n @for (key of objectKeys(metadata()); track key) {\n <div class=\"p-field\">\n <label [for]=\"key\">{{ key }}</label>\n <input pInputText [id]=\"key\" [(ngModel)]=\"metadataInput[key]\" />\n </div>\n }\n\n <div class=\"p-field\">\n <label for=\"emotion\">Emotion</label>\n <br />\n <p-select [options]=\"MoodStateOptions\" [(ngModel)]=\"moodSelected\" optionLabel=\"label\" optionValue=\"value\" placeholder=\"Select an emotion\"></p-select>\n </div>\n <div class=\"p-field\">\n <label for=\"emotion\">Event</label>\n <br />\n <p-select\n [options]=\"CharacterEventActions\"\n [(ngModel)]=\"eventSelected\"\n optionLabel=\"label\"\n optionValue=\"value\"\n placeholder=\"Select an event\"></p-select>\n </div>\n </div>\n </div>\n }\n </div>\n\n <ng-template pTemplate=\"footer\">\n <div class=\"dialog-footer\">\n <p-button label=\"Cancel\" styleClass=\"p-button-secondary\" (click)=\"displayDialog.set(false)\"></p-button>\n <p-button label=\"Upload\" (click)=\"uploadFile()\" [disabled]=\"!fileSelected() || isLoading()\"></p-button>\n </div>\n </ng-template>\n</p-dialog>\n}\n" }]
|
|
803
|
-
}], ctorParameters: () => [] });
|
|
780
|
+
}], ctorParameters: () => [], propDecorators: { storagePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "storagePath", required: true }] }], buttonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonLabel", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], metadata: [{ type: i0.Input, args: [{ isSignal: true, alias: "metadata", required: false }] }], fileUploaded: [{ type: i0.Output, args: ["fileUploaded"] }], uploadError: [{ type: i0.Output, args: ["uploadError"] }] } });
|
|
804
781
|
|
|
805
782
|
class DCFilesCacheService {
|
|
806
783
|
constructor() {
|
|
@@ -838,10 +815,10 @@ class DCFilesCacheService {
|
|
|
838
815
|
const blob = await this.getBlob(url);
|
|
839
816
|
return URL.createObjectURL(blob);
|
|
840
817
|
}
|
|
841
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
842
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
818
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DCFilesCacheService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
819
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DCFilesCacheService, providedIn: 'root' }); }
|
|
843
820
|
}
|
|
844
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
821
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DCFilesCacheService, decorators: [{
|
|
845
822
|
type: Injectable,
|
|
846
823
|
args: [{
|
|
847
824
|
providedIn: 'root',
|
|
@@ -936,16 +913,337 @@ class MultiObjectStorageService {
|
|
|
936
913
|
};
|
|
937
914
|
return meta;
|
|
938
915
|
}
|
|
939
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
940
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
916
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: MultiObjectStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
917
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: MultiObjectStorageService, providedIn: 'root' }); }
|
|
918
|
+
}
|
|
919
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: MultiObjectStorageService, decorators: [{
|
|
920
|
+
type: Injectable,
|
|
921
|
+
args: [{
|
|
922
|
+
providedIn: 'root',
|
|
923
|
+
}]
|
|
924
|
+
}] });
|
|
925
|
+
|
|
926
|
+
class FirebaseStorageProvider {
|
|
927
|
+
constructor() {
|
|
928
|
+
this.storage = inject(AngularFireStorage);
|
|
929
|
+
}
|
|
930
|
+
async uploadImage(image, path) {
|
|
931
|
+
try {
|
|
932
|
+
const refStorage = this.storage.ref(path);
|
|
933
|
+
const task = await refStorage.put(image);
|
|
934
|
+
const url = await lastValueFrom(refStorage.getDownloadURL());
|
|
935
|
+
return {
|
|
936
|
+
url,
|
|
937
|
+
name: task.metadata.name,
|
|
938
|
+
type: task.metadata.contentType,
|
|
939
|
+
size: task.metadata.size,
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
catch (error) {
|
|
943
|
+
console.error('Firebase upload image error:', error);
|
|
944
|
+
return null;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
async uploadGenericFile(file, storagePath, metadata, keepOriginalName) {
|
|
948
|
+
try {
|
|
949
|
+
const fileName = keepOriginalName ? file.name : `${Date.now()}-${file.name}`;
|
|
950
|
+
const fullFilePath = `${storagePath.replace(/\/$/, '')}/${fileName}`;
|
|
951
|
+
const refStorage = this.storage.ref(fullFilePath);
|
|
952
|
+
const task = await refStorage.put(file, { customMetadata: metadata });
|
|
953
|
+
const url = await lastValueFrom(refStorage.getDownloadURL());
|
|
954
|
+
return {
|
|
955
|
+
url,
|
|
956
|
+
name: file.name,
|
|
957
|
+
type: file.type,
|
|
958
|
+
size: file.size,
|
|
959
|
+
metadata: task.metadata,
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
catch (error) {
|
|
963
|
+
console.error('Firebase upload generic file error:', error);
|
|
964
|
+
return null;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
async uploadMultipleFiles(files, storagePath, metadata, keepOriginalName) {
|
|
968
|
+
try {
|
|
969
|
+
const uploadPromises = files.map(file => this.uploadGenericFile(file, storagePath, metadata, keepOriginalName));
|
|
970
|
+
const results = await Promise.all(uploadPromises);
|
|
971
|
+
return results.filter((r) => r !== null);
|
|
972
|
+
}
|
|
973
|
+
catch (error) {
|
|
974
|
+
console.error('Firebase upload multiple files error:', error);
|
|
975
|
+
return null;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
async deleteImage(imagePath) {
|
|
979
|
+
const storageRef = this.storage.ref(imagePath);
|
|
980
|
+
await lastValueFrom(storageRef.delete());
|
|
981
|
+
}
|
|
982
|
+
async deleteDirectory(directoryPath) {
|
|
983
|
+
const storage = getStorage();
|
|
984
|
+
const directoryRef = ref(storage, directoryPath);
|
|
985
|
+
const res = await listAll(directoryRef);
|
|
986
|
+
const promises = res.items.map((itemRef) => deleteObject(itemRef));
|
|
987
|
+
await Promise.all(promises);
|
|
988
|
+
}
|
|
989
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: FirebaseStorageProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
990
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: FirebaseStorageProvider, providedIn: 'root' }); }
|
|
991
|
+
}
|
|
992
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: FirebaseStorageProvider, decorators: [{
|
|
993
|
+
type: Injectable,
|
|
994
|
+
args: [{
|
|
995
|
+
providedIn: 'root',
|
|
996
|
+
}]
|
|
997
|
+
}] });
|
|
998
|
+
|
|
999
|
+
class BackendStorageProvider {
|
|
1000
|
+
constructor() {
|
|
1001
|
+
this.http = inject(HttpClient);
|
|
1002
|
+
this.appConfig = inject(APP_CONFIG);
|
|
1003
|
+
this.apiUrl = this.appConfig.backendNodeUrl + '/storage'; // This should ideally come from an environment config
|
|
1004
|
+
}
|
|
1005
|
+
async uploadImage(image, path) {
|
|
1006
|
+
const formData = new FormData();
|
|
1007
|
+
formData.append('file', image, 'image.webp');
|
|
1008
|
+
const params = {
|
|
1009
|
+
path,
|
|
1010
|
+
provider: 'GOOGLE'
|
|
1011
|
+
};
|
|
1012
|
+
try {
|
|
1013
|
+
return await firstValueFrom(this.http.post(`${this.apiUrl}/upload`, formData, { params }));
|
|
1014
|
+
}
|
|
1015
|
+
catch (error) {
|
|
1016
|
+
console.error('Backend upload image error:', error);
|
|
1017
|
+
return null;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
async uploadGenericFile(file, storagePath, metadata, keepOriginalName) {
|
|
1021
|
+
const formData = new FormData();
|
|
1022
|
+
if (metadata) {
|
|
1023
|
+
formData.append('metadata', JSON.stringify(metadata));
|
|
1024
|
+
}
|
|
1025
|
+
formData.append('file', file);
|
|
1026
|
+
const params = {
|
|
1027
|
+
path: storagePath,
|
|
1028
|
+
provider: 'GOOGLE'
|
|
1029
|
+
};
|
|
1030
|
+
if (keepOriginalName) {
|
|
1031
|
+
params.keepOriginalName = 'true';
|
|
1032
|
+
}
|
|
1033
|
+
try {
|
|
1034
|
+
return await firstValueFrom(this.http.post(`${this.apiUrl}/upload`, formData, { params }));
|
|
1035
|
+
}
|
|
1036
|
+
catch (error) {
|
|
1037
|
+
console.error('Backend upload generic file error:', error);
|
|
1038
|
+
return null;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
async uploadMultipleFiles(files, storagePath, metadata, keepOriginalName) {
|
|
1042
|
+
const formData = new FormData();
|
|
1043
|
+
if (metadata) {
|
|
1044
|
+
formData.append('metadata', JSON.stringify(metadata));
|
|
1045
|
+
}
|
|
1046
|
+
files.forEach(file => {
|
|
1047
|
+
formData.append('file', file, file.name);
|
|
1048
|
+
});
|
|
1049
|
+
const params = {
|
|
1050
|
+
path: storagePath,
|
|
1051
|
+
provider: 'GOOGLE'
|
|
1052
|
+
};
|
|
1053
|
+
if (keepOriginalName) {
|
|
1054
|
+
params.keepOriginalName = 'true';
|
|
1055
|
+
}
|
|
1056
|
+
try {
|
|
1057
|
+
return await firstValueFrom(this.http.post(`${this.apiUrl}/upload-multiple`, formData, { params }));
|
|
1058
|
+
}
|
|
1059
|
+
catch (error) {
|
|
1060
|
+
console.error('Backend upload multiple files error:', error);
|
|
1061
|
+
return null;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
async deleteImage(imagePath) {
|
|
1065
|
+
// Implement delete if the backend controller supports it
|
|
1066
|
+
console.warn('Backend delete image not implemented yet');
|
|
1067
|
+
}
|
|
1068
|
+
async deleteDirectory(directoryPath) {
|
|
1069
|
+
// Implement delete directory if the backend controller supports it
|
|
1070
|
+
console.warn('Backend delete directory not implemented yet');
|
|
1071
|
+
}
|
|
1072
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: BackendStorageProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1073
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: BackendStorageProvider, providedIn: 'root' }); }
|
|
941
1074
|
}
|
|
942
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1075
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: BackendStorageProvider, decorators: [{
|
|
943
1076
|
type: Injectable,
|
|
944
1077
|
args: [{
|
|
945
1078
|
providedIn: 'root',
|
|
946
1079
|
}]
|
|
947
1080
|
}] });
|
|
948
1081
|
|
|
1082
|
+
const STORAGE_PROVIDER_TYPE = new InjectionToken('STORAGE_PROVIDER_TYPE');
|
|
1083
|
+
class UniversalStorageService {
|
|
1084
|
+
constructor() {
|
|
1085
|
+
this.firebaseProvider = inject(FirebaseStorageProvider);
|
|
1086
|
+
this.backendProvider = inject(BackendStorageProvider);
|
|
1087
|
+
this.providerType = inject(STORAGE_PROVIDER_TYPE, { optional: true }) || 'FIREBASE';
|
|
1088
|
+
}
|
|
1089
|
+
get provider() {
|
|
1090
|
+
return this.providerType === 'BACKEND' ? this.backendProvider : this.firebaseProvider;
|
|
1091
|
+
}
|
|
1092
|
+
async uploadImage(image, path) {
|
|
1093
|
+
return this.provider.uploadImage(image, path);
|
|
1094
|
+
}
|
|
1095
|
+
uploadGenericFile(file, storagePath, metadata, keepOriginalName) {
|
|
1096
|
+
return this.provider.uploadGenericFile(file, storagePath, metadata, keepOriginalName);
|
|
1097
|
+
}
|
|
1098
|
+
uploadMultipleFiles(files, storagePath, metadata, keepOriginalName) {
|
|
1099
|
+
return this.provider.uploadMultipleFiles(files, storagePath, metadata, keepOriginalName);
|
|
1100
|
+
}
|
|
1101
|
+
async deleteImage(imagePath) {
|
|
1102
|
+
return this.provider.deleteImage(imagePath);
|
|
1103
|
+
}
|
|
1104
|
+
async deleteDirectory(directoryPath) {
|
|
1105
|
+
return this.provider.deleteDirectory(directoryPath);
|
|
1106
|
+
}
|
|
1107
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: UniversalStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1108
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: UniversalStorageService, providedIn: 'root' }); }
|
|
1109
|
+
}
|
|
1110
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: UniversalStorageService, decorators: [{
|
|
1111
|
+
type: Injectable,
|
|
1112
|
+
args: [{
|
|
1113
|
+
providedIn: 'root',
|
|
1114
|
+
}]
|
|
1115
|
+
}] });
|
|
1116
|
+
|
|
1117
|
+
class BackendUploadComponent {
|
|
1118
|
+
constructor() {
|
|
1119
|
+
this.storageService = inject(UniversalStorageService);
|
|
1120
|
+
this.onUploadFinish = new EventEmitter();
|
|
1121
|
+
this.storagePath = 'test-uploads';
|
|
1122
|
+
this.keepOriginalNames = true;
|
|
1123
|
+
this.uploading = signal(false, ...(ngDevMode ? [{ debugName: "uploading" }] : []));
|
|
1124
|
+
this.status = signal(null, ...(ngDevMode ? [{ debugName: "status" }] : []));
|
|
1125
|
+
this.message = signal('', ...(ngDevMode ? [{ debugName: "message" }] : []));
|
|
1126
|
+
this.uploadedFileUrls = signal([], ...(ngDevMode ? [{ debugName: "uploadedFileUrls" }] : []));
|
|
1127
|
+
this.totalSize = signal(0, ...(ngDevMode ? [{ debugName: "totalSize" }] : []));
|
|
1128
|
+
this.totalSizePercent = signal(0, ...(ngDevMode ? [{ debugName: "totalSizePercent" }] : []));
|
|
1129
|
+
}
|
|
1130
|
+
async onUpload(event) {
|
|
1131
|
+
console.log('Upload event:', event);
|
|
1132
|
+
const files = event.files;
|
|
1133
|
+
if (!files || files.length === 0)
|
|
1134
|
+
return;
|
|
1135
|
+
this.uploading.set(true);
|
|
1136
|
+
this.status.set(null);
|
|
1137
|
+
this.message.set('Uploading...');
|
|
1138
|
+
try {
|
|
1139
|
+
// Group files by upload path to use multi-file upload where possible
|
|
1140
|
+
const groupedFiles = {};
|
|
1141
|
+
files.forEach(file => {
|
|
1142
|
+
let uploadPath = this.storagePath;
|
|
1143
|
+
if (file.webkitRelativePath) {
|
|
1144
|
+
const relativeDir = file.webkitRelativePath.substring(0, file.webkitRelativePath.lastIndexOf('/'));
|
|
1145
|
+
if (relativeDir) {
|
|
1146
|
+
uploadPath = `${this.storagePath}/${relativeDir}`;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
if (!groupedFiles[uploadPath]) {
|
|
1150
|
+
groupedFiles[uploadPath] = [];
|
|
1151
|
+
}
|
|
1152
|
+
groupedFiles[uploadPath].push(file);
|
|
1153
|
+
});
|
|
1154
|
+
const uploadPromises = Object.entries(groupedFiles).map(([path, pathFiles]) => {
|
|
1155
|
+
return this.storageService.uploadMultipleFiles(pathFiles, path, null, this.keepOriginalNames);
|
|
1156
|
+
});
|
|
1157
|
+
const results = await Promise.all(uploadPromises);
|
|
1158
|
+
const flattenedResults = results.flat().filter(result => result && result.url);
|
|
1159
|
+
const urls = flattenedResults.map(result => result.url);
|
|
1160
|
+
if (urls.length > 0) {
|
|
1161
|
+
this.status.set('success');
|
|
1162
|
+
this.message.set(`${urls.length} file(s) uploaded successfully!`);
|
|
1163
|
+
this.uploadedFileUrls.update(current => [...current, ...urls]);
|
|
1164
|
+
this.onUploadFinish.emit(flattenedResults);
|
|
1165
|
+
}
|
|
1166
|
+
else {
|
|
1167
|
+
throw new Error('Upload failed: No files were uploaded');
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
catch (error) {
|
|
1171
|
+
console.error('Upload component error:', error);
|
|
1172
|
+
this.status.set('error');
|
|
1173
|
+
this.message.set(error.message || 'Error uploading files');
|
|
1174
|
+
}
|
|
1175
|
+
finally {
|
|
1176
|
+
this.uploading.set(false);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
onSelect(event) {
|
|
1180
|
+
console.log('Select event:', event);
|
|
1181
|
+
this.totalSize.set(0);
|
|
1182
|
+
event.currentFiles.forEach((file) => {
|
|
1183
|
+
this.totalSize.update(total => total + file.size);
|
|
1184
|
+
});
|
|
1185
|
+
this.totalSizePercent.set(Math.min((this.totalSize() / 10000000) * 100, 100)); // 10MB limit
|
|
1186
|
+
}
|
|
1187
|
+
onRemove(event) {
|
|
1188
|
+
this.totalSize.update(total => total - event.file.size);
|
|
1189
|
+
this.totalSizePercent.set(Math.min((this.totalSize() / 10000000) * 100, 100)); // 10MB limit
|
|
1190
|
+
}
|
|
1191
|
+
onClear() {
|
|
1192
|
+
this.totalSize.set(0);
|
|
1193
|
+
this.totalSizePercent.set(0);
|
|
1194
|
+
}
|
|
1195
|
+
choose(event, callback) {
|
|
1196
|
+
callback();
|
|
1197
|
+
}
|
|
1198
|
+
onFolderSelect(event) {
|
|
1199
|
+
const files = event.target.files;
|
|
1200
|
+
if (files && files.length > 0) {
|
|
1201
|
+
const fileList = Array.from(files);
|
|
1202
|
+
// Generate object URLs for preview
|
|
1203
|
+
fileList.forEach(file => {
|
|
1204
|
+
file.objectURL = URL.createObjectURL(file);
|
|
1205
|
+
});
|
|
1206
|
+
if (this.fileUpload) {
|
|
1207
|
+
this.fileUpload.files = [...this.fileUpload.files, ...fileList];
|
|
1208
|
+
// Let's also update our total size and UI signals
|
|
1209
|
+
this.onSelect({ currentFiles: this.fileUpload.files });
|
|
1210
|
+
}
|
|
1211
|
+
// Reset input value so same folder can be selected again
|
|
1212
|
+
event.target.value = '';
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
formatSize(bytes) {
|
|
1216
|
+
if (bytes === 0)
|
|
1217
|
+
return '0 B';
|
|
1218
|
+
const k = 1024;
|
|
1219
|
+
const dm = 2;
|
|
1220
|
+
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
1221
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
1222
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
|
1223
|
+
}
|
|
1224
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: BackendUploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1225
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: BackendUploadComponent, isStandalone: true, selector: "dc-backend-upload", inputs: { storagePath: "storagePath", keepOriginalNames: "keepOriginalNames" }, outputs: { onUploadFinish: "onUploadFinish" }, providers: [
|
|
1226
|
+
{ provide: STORAGE_PROVIDER_TYPE, useValue: 'BACKEND' },
|
|
1227
|
+
UniversalStorageService
|
|
1228
|
+
], viewQueries: [{ propertyName: "fileUpload", first: true, predicate: ["fu"], descendants: true }], ngImport: i0, template: "<div class=\"card p-4\">\n <p-toast />\n \n <p-fileupload \n #fu\n name=\"file\" \n [customUpload]=\"true\" \n (uploadHandler)=\"onUpload($event)\"\n (onSelect)=\"onSelect($event)\"\n (onRemove)=\"onRemove($event)\"\n (onClear)=\"onClear()\"\n [multiple]=\"true\" \n [maxFileSize]=\"10000000\" \n mode=\"advanced\">\n \n <ng-template #header let-files let-chooseCallback=\"chooseCallback\" let-clearCallback=\"clearCallback\" let-uploadCallback=\"uploadCallback\">\n <div class=\"flex flex-wrap justify-between items-center flex-1 gap-4\">\n <div class=\"flex gap-2\">\n <p-button (onClick)=\"choose($event, chooseCallback)\" icon=\"pi pi-plus\" [rounded]=\"true\" [outlined]=\"true\" label=\"Choose\" />\n <input #folderInput type=\"file\" webkitdirectory directory multiple style=\"display: none\" (change)=\"onFolderSelect($event)\">\n <p-button (onClick)=\"folderInput.click()\" icon=\"pi pi-folder-open\" [rounded]=\"true\" [outlined]=\"true\" label=\"Upload Folder\" severity=\"secondary\" />\n <p-button (onClick)=\"uploadCallback()\" icon=\"pi pi-cloud-upload\" [rounded]=\"true\" [outlined]=\"true\" severity=\"success\" [disabled]=\"!files || files.length === 0\" label=\"Upload\" />\n <p-button (onClick)=\"clearCallback()\" icon=\"pi pi-times\" [rounded]=\"true\" [outlined]=\"true\" severity=\"danger\" [disabled]=\"!files || files.length === 0\" label=\"Clear\" />\n </div>\n <div class=\"flex items-center gap-3 ml-auto\">\n <p-progressbar [value]=\"totalSizePercent()\" [showValue]=\"false\" class=\"w-full md:w-20rem h-1\">\n </p-progressbar>\n <span class=\"whitespace-nowrap text-sm text-secondary\">{{ formatSize(totalSize()) }} / 10MB</span>\n </div>\n </div>\n </ng-template>\n\n <ng-template #content let-files let-uploadedFiles=\"uploadedFiles\" let-removeFileCallback=\"removeFileCallback\" let-removeUploadedFileCallback=\"removeUploadedFileCallback\">\n <div class=\"flex flex-col gap-4 pt-4\">\n @if (files?.length > 0) {\n <div>\n <h5 class=\"mb-3 text-lg font-medium\">Pending Uploads</h5>\n <div class=\"flex flex-wrap gap-4\">\n @for (file of files; track file.name; let i = $index) {\n <div class=\"p-4 border rounded-lg border-surface-200 dark:border-surface-700 flex flex-col items-center gap-3 bg-surface-50 dark:bg-surface-900 w-48\">\n <div class=\"w-full h-24 flex items-center justify-center bg-surface-100 dark:bg-surface-800 rounded\">\n @if (file.objectURL) {\n <img role=\"presentation\" [alt]=\"file.name\" [src]=\"file.objectURL\" class=\"max-w-full max-h-full object-contain\" />\n } @else {\n <i class=\"pi pi-file text-4xl text-surface-400\"></i>\n }\n </div>\n <span class=\"font-semibold text-sm truncate w-full text-center\" [title]=\"file.webkitRelativePath || file.name\">\n {{ file.webkitRelativePath || file.name }}\n </span>\n <div class=\"text-xs text-secondary\">{{ formatSize(file.size) }}</div>\n <p-badge value=\"Pending\" severity=\"warn\" />\n <p-button icon=\"pi pi-times\" (onClick)=\"removeFileCallback($event, i)\" [outlined]=\"true\" [rounded]=\"true\" severity=\"danger\" size=\"small\" />\n </div>\n }\n </div>\n </div>\n }\n\n @if (uploadedFileUrls().length > 0) {\n <div class=\"mt-4\">\n <h5 class=\"mb-3 text-lg font-medium text-green-600\">Completed Uploads</h5>\n <div class=\"flex flex-wrap gap-4\">\n @for (url of uploadedFileUrls(); track url; let i = $index) {\n <div class=\"p-4 border rounded-lg border-green-200 dark:border-green-800 flex flex-col items-center gap-3 bg-green-50 dark:bg-green-900/20 w-48\">\n <div class=\"w-full h-24 flex items-center justify-center bg-surface-100 dark:bg-surface-800 rounded\">\n @if (url.toLowerCase().endsWith('.png') || url.toLowerCase().endsWith('.jpg') || url.toLowerCase().endsWith('.jpeg') || url.toLowerCase().endsWith('.webp')) {\n <img [src]=\"url\" class=\"max-w-full max-h-full object-contain\" />\n } @else {\n <i class=\"pi pi-check-circle text-4xl text-green-500\"></i>\n }\n </div>\n <span class=\"font-semibold text-sm truncate w-full text-center\">Uploaded File {{ i + 1 }}</span>\n <p-badge value=\"Completed\" severity=\"success\" />\n <a [href]=\"url\" target=\"_blank\" class=\"text-xs text-primary underline\">View File</a>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </ng-template>\n\n <ng-template #empty>\n <div class=\"flex items-center justify-center flex-col py-8 border-2 border-dashed border-surface-300 dark:border-surface-600 rounded-xl bg-surface-50 dark:bg-surface-900/50\">\n <i class=\"pi pi-cloud-upload text-5xl text-surface-400 mb-4\"></i>\n <p class=\"text-surface-600 dark:text-surface-400 font-medium\">Drag and drop files here to upload</p>\n <p class=\"text-surface-500 dark:text-surface-500 text-sm\">Any file type up to 10MB</p>\n </div>\n </ng-template>\n </p-fileupload>\n\n @if (status()) {\n <div class=\"mt-4 p-3 rounded-lg flex items-center gap-3\" [ngClass]=\"status() === 'success' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'\">\n <i [class]=\"status() === 'success' ? 'pi pi-check-circle' : 'pi pi-exclamation-circle'\"></i>\n <span>{{ message() }}</span>\n </div>\n }\n</div>\n", styles: [":host{display:block;margin:1rem 0}.upload-container{padding:1rem;border:1px dashed #ccc;border-radius:8px}.status-message{margin-top:1rem;padding:.5rem;border-radius:4px}.status-message.success{background-color:#d4edda;color:#155724}.status-message.error{background-color:#f8d7da;color:#721c24}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FileUploadModule }, { kind: "component", type: i2$1.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "ngmodule", type: ToastModule }, { kind: "component", type: i3$1.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "ngmodule", type: ProgressBarModule }, { kind: "component", type: i4$1.ProgressBar, selector: "p-progressBar, p-progressbar, p-progress-bar", inputs: ["value", "showValue", "styleClass", "valueStyleClass", "unit", "mode", "color"] }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i5$1.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }] }); }
|
|
1229
|
+
}
|
|
1230
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: BackendUploadComponent, decorators: [{
|
|
1231
|
+
type: Component,
|
|
1232
|
+
args: [{ selector: 'dc-backend-upload', standalone: true, imports: [CommonModule, FileUploadModule, ToastModule, ProgressBarModule, BadgeModule, ButtonModule], providers: [
|
|
1233
|
+
{ provide: STORAGE_PROVIDER_TYPE, useValue: 'BACKEND' },
|
|
1234
|
+
UniversalStorageService
|
|
1235
|
+
], template: "<div class=\"card p-4\">\n <p-toast />\n \n <p-fileupload \n #fu\n name=\"file\" \n [customUpload]=\"true\" \n (uploadHandler)=\"onUpload($event)\"\n (onSelect)=\"onSelect($event)\"\n (onRemove)=\"onRemove($event)\"\n (onClear)=\"onClear()\"\n [multiple]=\"true\" \n [maxFileSize]=\"10000000\" \n mode=\"advanced\">\n \n <ng-template #header let-files let-chooseCallback=\"chooseCallback\" let-clearCallback=\"clearCallback\" let-uploadCallback=\"uploadCallback\">\n <div class=\"flex flex-wrap justify-between items-center flex-1 gap-4\">\n <div class=\"flex gap-2\">\n <p-button (onClick)=\"choose($event, chooseCallback)\" icon=\"pi pi-plus\" [rounded]=\"true\" [outlined]=\"true\" label=\"Choose\" />\n <input #folderInput type=\"file\" webkitdirectory directory multiple style=\"display: none\" (change)=\"onFolderSelect($event)\">\n <p-button (onClick)=\"folderInput.click()\" icon=\"pi pi-folder-open\" [rounded]=\"true\" [outlined]=\"true\" label=\"Upload Folder\" severity=\"secondary\" />\n <p-button (onClick)=\"uploadCallback()\" icon=\"pi pi-cloud-upload\" [rounded]=\"true\" [outlined]=\"true\" severity=\"success\" [disabled]=\"!files || files.length === 0\" label=\"Upload\" />\n <p-button (onClick)=\"clearCallback()\" icon=\"pi pi-times\" [rounded]=\"true\" [outlined]=\"true\" severity=\"danger\" [disabled]=\"!files || files.length === 0\" label=\"Clear\" />\n </div>\n <div class=\"flex items-center gap-3 ml-auto\">\n <p-progressbar [value]=\"totalSizePercent()\" [showValue]=\"false\" class=\"w-full md:w-20rem h-1\">\n </p-progressbar>\n <span class=\"whitespace-nowrap text-sm text-secondary\">{{ formatSize(totalSize()) }} / 10MB</span>\n </div>\n </div>\n </ng-template>\n\n <ng-template #content let-files let-uploadedFiles=\"uploadedFiles\" let-removeFileCallback=\"removeFileCallback\" let-removeUploadedFileCallback=\"removeUploadedFileCallback\">\n <div class=\"flex flex-col gap-4 pt-4\">\n @if (files?.length > 0) {\n <div>\n <h5 class=\"mb-3 text-lg font-medium\">Pending Uploads</h5>\n <div class=\"flex flex-wrap gap-4\">\n @for (file of files; track file.name; let i = $index) {\n <div class=\"p-4 border rounded-lg border-surface-200 dark:border-surface-700 flex flex-col items-center gap-3 bg-surface-50 dark:bg-surface-900 w-48\">\n <div class=\"w-full h-24 flex items-center justify-center bg-surface-100 dark:bg-surface-800 rounded\">\n @if (file.objectURL) {\n <img role=\"presentation\" [alt]=\"file.name\" [src]=\"file.objectURL\" class=\"max-w-full max-h-full object-contain\" />\n } @else {\n <i class=\"pi pi-file text-4xl text-surface-400\"></i>\n }\n </div>\n <span class=\"font-semibold text-sm truncate w-full text-center\" [title]=\"file.webkitRelativePath || file.name\">\n {{ file.webkitRelativePath || file.name }}\n </span>\n <div class=\"text-xs text-secondary\">{{ formatSize(file.size) }}</div>\n <p-badge value=\"Pending\" severity=\"warn\" />\n <p-button icon=\"pi pi-times\" (onClick)=\"removeFileCallback($event, i)\" [outlined]=\"true\" [rounded]=\"true\" severity=\"danger\" size=\"small\" />\n </div>\n }\n </div>\n </div>\n }\n\n @if (uploadedFileUrls().length > 0) {\n <div class=\"mt-4\">\n <h5 class=\"mb-3 text-lg font-medium text-green-600\">Completed Uploads</h5>\n <div class=\"flex flex-wrap gap-4\">\n @for (url of uploadedFileUrls(); track url; let i = $index) {\n <div class=\"p-4 border rounded-lg border-green-200 dark:border-green-800 flex flex-col items-center gap-3 bg-green-50 dark:bg-green-900/20 w-48\">\n <div class=\"w-full h-24 flex items-center justify-center bg-surface-100 dark:bg-surface-800 rounded\">\n @if (url.toLowerCase().endsWith('.png') || url.toLowerCase().endsWith('.jpg') || url.toLowerCase().endsWith('.jpeg') || url.toLowerCase().endsWith('.webp')) {\n <img [src]=\"url\" class=\"max-w-full max-h-full object-contain\" />\n } @else {\n <i class=\"pi pi-check-circle text-4xl text-green-500\"></i>\n }\n </div>\n <span class=\"font-semibold text-sm truncate w-full text-center\">Uploaded File {{ i + 1 }}</span>\n <p-badge value=\"Completed\" severity=\"success\" />\n <a [href]=\"url\" target=\"_blank\" class=\"text-xs text-primary underline\">View File</a>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </ng-template>\n\n <ng-template #empty>\n <div class=\"flex items-center justify-center flex-col py-8 border-2 border-dashed border-surface-300 dark:border-surface-600 rounded-xl bg-surface-50 dark:bg-surface-900/50\">\n <i class=\"pi pi-cloud-upload text-5xl text-surface-400 mb-4\"></i>\n <p class=\"text-surface-600 dark:text-surface-400 font-medium\">Drag and drop files here to upload</p>\n <p class=\"text-surface-500 dark:text-surface-500 text-sm\">Any file type up to 10MB</p>\n </div>\n </ng-template>\n </p-fileupload>\n\n @if (status()) {\n <div class=\"mt-4 p-3 rounded-lg flex items-center gap-3\" [ngClass]=\"status() === 'success' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'\">\n <i [class]=\"status() === 'success' ? 'pi pi-check-circle' : 'pi pi-exclamation-circle'\"></i>\n <span>{{ message() }}</span>\n </div>\n }\n</div>\n", styles: [":host{display:block;margin:1rem 0}.upload-container{padding:1rem;border:1px dashed #ccc;border-radius:8px}.status-message{margin-top:1rem;padding:.5rem;border-radius:4px}.status-message.success{background-color:#d4edda;color:#155724}.status-message.error{background-color:#f8d7da;color:#721c24}\n"] }]
|
|
1236
|
+
}], propDecorators: { fileUpload: [{
|
|
1237
|
+
type: ViewChild,
|
|
1238
|
+
args: ['fu']
|
|
1239
|
+
}], onUploadFinish: [{
|
|
1240
|
+
type: Output
|
|
1241
|
+
}], storagePath: [{
|
|
1242
|
+
type: Input
|
|
1243
|
+
}], keepOriginalNames: [{
|
|
1244
|
+
type: Input
|
|
1245
|
+
}] } });
|
|
1246
|
+
|
|
949
1247
|
class AssetsLoaderComponent {
|
|
950
1248
|
constructor() {
|
|
951
1249
|
this.assets = input.required(...(ngDevMode ? [{ debugName: "assets" }] : []));
|
|
@@ -1063,13 +1361,13 @@ class AssetsLoaderComponent {
|
|
|
1063
1361
|
clearInterval(this.reverseInterval);
|
|
1064
1362
|
}
|
|
1065
1363
|
}
|
|
1066
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1067
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1364
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AssetsLoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1365
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: AssetsLoaderComponent, isStandalone: true, selector: "assets-loader", inputs: { assets: { classPropertyName: "assets", publicName: "assets", isSignal: true, isRequired: true, transformFunction: null }, storagePath: { classPropertyName: "storagePath", publicName: "storagePath", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { assetsChange: "assetsChange", assetUpdate: "assetUpdate", onFileSelected: "onFileSelected" }, ngImport: i0, template: "<div class=\"assets-container\">\n <div class=\"assets-card\">\n <p-message severity=\"info\">\n <div class=\"upload-buttons\">\n <div>\n <dc-cropper-modal\n id=\"cropperCardImage\"\n #cropperCardImage\n [buttonLabel]=\"assets()?.image?.url ? 'Cambiar imagen' : 'Cargar una imagen'\"\n [imgStorageSettings]=\"imageStorageSettings()\"\n [currentStorage]=\"assets()?.image\"\n (imageUploaded)=\"onImageUploaded($event, 'image')\"\n (onFileSelected)=\"onFileSelected.emit($event)\"></dc-cropper-modal>\n </div>\n\n <dc-simple-uploader\n [buttonLabel]=\"assets()?.motion?.url ? 'Cambiar video principal' : 'Agregar video principal'\"\n (fileUploaded)=\"onMotionUploaded($event)\"\n [storagePath]=\"storagePath() + '/motions/file'\"\n [accept]=\"'video/*'\"></dc-simple-uploader>\n\n <dc-simple-uploader\n [buttonLabel]=\"'Agregar Movimientos'\"\n (fileUploaded)=\"onMotionAdded($event)\"\n [storagePath]=\"storagePath() + '/motions/file'\"\n [accept]=\"'video/*'\"></dc-simple-uploader>\n\n <dc-cropper-modal\n #cropperBanner\n id=\"cropperBanner\"\n [buttonLabel]=\"assets()?.banner?.url ? 'Cambiar el banner' : 'Cargar un banner'\"\n [imgStorageSettings]=\"bannerImgSettings()\"\n [currentStorage]=\"assets()?.banner\"\n (imageUploaded)=\"onImageUploaded($event, 'banner')\"></dc-cropper-modal>\n\n <dc-cropper-modal\n id=\"cropperStickers\"\n #cropperStickers\n [buttonLabel]=\"'Agregar sticker'\"\n [imgStorageSettings]=\"stickerStorageSettings()\"\n (imageUploaded)=\"onImageUploaded($event, 'sticker')\"></dc-cropper-modal>\n </div>\n </p-message>\n <!-- Banner -->\n\n <div class=\"preview-container\">\n <img [src]=\"assets()?.banner?.url || 'defaults/images/default_banner.webp'\" class=\"main-banner-image-card\" />\n <div class=\"main-image-card\">\n <img [src]=\"assets()?.image?.url || 'defaults/images/default_2_3.webp'\" />\n </div>\n\n <div class=\"motion-container\">\n <video #videoPlayer class=\"main-motion-card\" [src]=\"assets()?.motion?.url\" (ended)=\"onVideoEnded(videoPlayer)\" autoplay muted playsinline></video>\n @if(assets()?.motion?.url){\n <p-button class=\"remove-main-motion-button\" (click)=\"removeMainMotion()\" [rounded]=\"true\" [text]=\"true\" icon=\"pi pi-trash\" severity=\"danger\"></p-button>\n }\n </div>\n </div>\n\n <div class=\"stickers-container\">\n @for (sticker of assets()?.stickers; track sticker.url) {\n <div class=\"sticker-wrapper\">\n <img width=\"100\" [src]=\"sticker.url\" alt=\"\" />\n <p-button (click)=\"removeSticker(sticker)\" class=\"remove-sticker\" icon=\"pi pi-times\" [rounded]=\"true\" [text]=\"true\" severity=\"danger\" />\n </div>\n }\n </div>\n\n <div class=\"motions-container\">\n @for (motion of assets()?.motions; track motion.url) {\n <div class=\"motion-wrapper\">\n <video width=\"150\" [src]=\"motion.url\" controls playsinline preload=\"none\"></video>\n <p-button (click)=\"removeMotion(motion)\" class=\"remove-motion-button\" icon=\"pi pi-trash\" [rounded]=\"true\" [text]=\"true\" severity=\"danger\"></p-button>\n @if(motion.metadata?.moodState){\n <p-tag style=\"position: absolute; top: 4px; left: 4px\" severity=\"secondary\" [value]=\"motion.metadata?.moodState\" />\n } @if(motion.metadata?.event){\n <p-tag style=\"position: absolute; top: 4px; left: 4px\" severity=\"warn\" [value]=\"motion.metadata?.event\" />\n }\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [".main-image-card{max-width:220px;display:block;border-radius:8px;position:absolute;bottom:-100px;left:20px;transform:none;z-index:1;box-shadow:0 4px 8px #0003;overflow:hidden}@media(max-width:1300px){.main-image-card{max-width:170px}}@media(max-width:768px){.main-image-card{max-width:130px}}.main-motion-card{max-width:100%;display:block;border-radius:8px}.main-banner-image-card{display:block;width:100%;max-height:400px;object-fit:cover;border-radius:8px}.remove-sticker{position:absolute;top:5px;right:5px}.assets-container{position:relative;min-height:60px}.assets-card{border:1px dashed rgba(12,19,142,.1215686275);padding:4px;border-radius:15px}.upload-buttons{display:flex;gap:10px}.preview-container{position:relative;margin-bottom:100px}.stickers-container{display:flex;flex-wrap:wrap;gap:10px}.sticker-wrapper{position:relative}.motion-container{position:absolute;bottom:-100px;right:20px;z-index:1;box-shadow:0 4px 8px #0003;max-width:220px;border-radius:8px;overflow:hidden}@media(max-width:1300px){.motion-container{max-width:170px}}@media(max-width:768px){.motion-container{max-width:130px}}.remove-main-motion-button{position:absolute;top:10px;right:10px;z-index:2}.motions-container{display:flex;flex-wrap:wrap;gap:10px;margin-top:20px}.motion-wrapper{position:relative;width:150px;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}.motion-wrapper video{min-height:220px;display:block;background-color:#f0f0f0}.remove-motion-button{position:absolute;top:5px;right:5px;z-index:2}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: CropperComponentModal, selector: "dc-cropper-modal", inputs: ["imgStorageSettings", "buttonLabel", "currentStorage"], outputs: ["imageUploaded", "onImageCropped", "onFileSelected"] }, { kind: "component", type: SimpleUploaderComponent, selector: "dc-simple-uploader", inputs: ["storagePath", "buttonLabel", "accept", "disabled", "metadata"], outputs: ["fileUploaded", "uploadError"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: i6.Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant", "motionOptions"], outputs: ["onClose"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i3$2.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }] }); }
|
|
1068
1366
|
}
|
|
1069
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1367
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AssetsLoaderComponent, decorators: [{
|
|
1070
1368
|
type: Component,
|
|
1071
|
-
args: [{ selector: 'assets-loader', standalone: true, imports: [CommonModule, CropperComponentModal, SimpleUploaderComponent, ButtonModule, MessageModule, TagModule], template: "<div class=\"assets-container\">\n <div class=\"assets-card\">\n <p-message severity=\"info\">\n <div class=\"upload-buttons\">\n <div>\n <dc-cropper-modal\n id=\"cropperCardImage\"\n #cropperCardImage\n [buttonLabel]=\"assets()?.image?.url ? 'Cambiar imagen' : 'Cargar una imagen'\"\n [imgStorageSettings]=\"imageStorageSettings()\"\n [currentStorage]=\"assets()?.image\"\n (imageUploaded)=\"onImageUploaded($event, 'image')\"\n (onFileSelected)=\"onFileSelected.emit($event)\"></dc-cropper-modal>\n </div>\n\n <dc-simple-uploader\n [buttonLabel]=\"assets()?.motion?.url ? 'Cambiar video principal' : 'Agregar video principal'\"\n (fileUploaded)=\"onMotionUploaded($event)\"\n [storagePath]=\"storagePath() + '/motions/file'\"\n [accept]=\"'video/*'\"></dc-simple-uploader>\n\n <dc-simple-uploader\n [buttonLabel]=\"'Agregar Movimientos'\"\n (fileUploaded)=\"onMotionAdded($event)\"\n [storagePath]=\"storagePath() + '/motions/file'\"\n [accept]=\"'video/*'\"></dc-simple-uploader>\n\n <dc-cropper-modal\n #cropperBanner\n id=\"cropperBanner\"\n [buttonLabel]=\"assets()?.banner?.url ? 'Cambiar el banner' : 'Cargar un banner'\"\n [imgStorageSettings]=\"bannerImgSettings()\"\n [currentStorage]=\"assets()?.banner\"\n (imageUploaded)=\"onImageUploaded($event, 'banner')\"></dc-cropper-modal>\n\n <dc-cropper-modal\n id=\"cropperStickers\"\n #cropperStickers\n [buttonLabel]=\"'Agregar sticker'\"\n [imgStorageSettings]=\"stickerStorageSettings()\"\n (imageUploaded)=\"onImageUploaded($event, 'sticker')\"></dc-cropper-modal>\n </div>\n </p-message>\n <!-- Banner -->\n\n <div class=\"preview-container\">\n <img [src]=\"assets()?.banner?.url || '
|
|
1072
|
-
}] });
|
|
1369
|
+
args: [{ selector: 'assets-loader', standalone: true, imports: [CommonModule, CropperComponentModal, SimpleUploaderComponent, ButtonModule, MessageModule, TagModule], template: "<div class=\"assets-container\">\n <div class=\"assets-card\">\n <p-message severity=\"info\">\n <div class=\"upload-buttons\">\n <div>\n <dc-cropper-modal\n id=\"cropperCardImage\"\n #cropperCardImage\n [buttonLabel]=\"assets()?.image?.url ? 'Cambiar imagen' : 'Cargar una imagen'\"\n [imgStorageSettings]=\"imageStorageSettings()\"\n [currentStorage]=\"assets()?.image\"\n (imageUploaded)=\"onImageUploaded($event, 'image')\"\n (onFileSelected)=\"onFileSelected.emit($event)\"></dc-cropper-modal>\n </div>\n\n <dc-simple-uploader\n [buttonLabel]=\"assets()?.motion?.url ? 'Cambiar video principal' : 'Agregar video principal'\"\n (fileUploaded)=\"onMotionUploaded($event)\"\n [storagePath]=\"storagePath() + '/motions/file'\"\n [accept]=\"'video/*'\"></dc-simple-uploader>\n\n <dc-simple-uploader\n [buttonLabel]=\"'Agregar Movimientos'\"\n (fileUploaded)=\"onMotionAdded($event)\"\n [storagePath]=\"storagePath() + '/motions/file'\"\n [accept]=\"'video/*'\"></dc-simple-uploader>\n\n <dc-cropper-modal\n #cropperBanner\n id=\"cropperBanner\"\n [buttonLabel]=\"assets()?.banner?.url ? 'Cambiar el banner' : 'Cargar un banner'\"\n [imgStorageSettings]=\"bannerImgSettings()\"\n [currentStorage]=\"assets()?.banner\"\n (imageUploaded)=\"onImageUploaded($event, 'banner')\"></dc-cropper-modal>\n\n <dc-cropper-modal\n id=\"cropperStickers\"\n #cropperStickers\n [buttonLabel]=\"'Agregar sticker'\"\n [imgStorageSettings]=\"stickerStorageSettings()\"\n (imageUploaded)=\"onImageUploaded($event, 'sticker')\"></dc-cropper-modal>\n </div>\n </p-message>\n <!-- Banner -->\n\n <div class=\"preview-container\">\n <img [src]=\"assets()?.banner?.url || 'defaults/images/default_banner.webp'\" class=\"main-banner-image-card\" />\n <div class=\"main-image-card\">\n <img [src]=\"assets()?.image?.url || 'defaults/images/default_2_3.webp'\" />\n </div>\n\n <div class=\"motion-container\">\n <video #videoPlayer class=\"main-motion-card\" [src]=\"assets()?.motion?.url\" (ended)=\"onVideoEnded(videoPlayer)\" autoplay muted playsinline></video>\n @if(assets()?.motion?.url){\n <p-button class=\"remove-main-motion-button\" (click)=\"removeMainMotion()\" [rounded]=\"true\" [text]=\"true\" icon=\"pi pi-trash\" severity=\"danger\"></p-button>\n }\n </div>\n </div>\n\n <div class=\"stickers-container\">\n @for (sticker of assets()?.stickers; track sticker.url) {\n <div class=\"sticker-wrapper\">\n <img width=\"100\" [src]=\"sticker.url\" alt=\"\" />\n <p-button (click)=\"removeSticker(sticker)\" class=\"remove-sticker\" icon=\"pi pi-times\" [rounded]=\"true\" [text]=\"true\" severity=\"danger\" />\n </div>\n }\n </div>\n\n <div class=\"motions-container\">\n @for (motion of assets()?.motions; track motion.url) {\n <div class=\"motion-wrapper\">\n <video width=\"150\" [src]=\"motion.url\" controls playsinline preload=\"none\"></video>\n <p-button (click)=\"removeMotion(motion)\" class=\"remove-motion-button\" icon=\"pi pi-trash\" [rounded]=\"true\" [text]=\"true\" severity=\"danger\"></p-button>\n @if(motion.metadata?.moodState){\n <p-tag style=\"position: absolute; top: 4px; left: 4px\" severity=\"secondary\" [value]=\"motion.metadata?.moodState\" />\n } @if(motion.metadata?.event){\n <p-tag style=\"position: absolute; top: 4px; left: 4px\" severity=\"warn\" [value]=\"motion.metadata?.event\" />\n }\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [".main-image-card{max-width:220px;display:block;border-radius:8px;position:absolute;bottom:-100px;left:20px;transform:none;z-index:1;box-shadow:0 4px 8px #0003;overflow:hidden}@media(max-width:1300px){.main-image-card{max-width:170px}}@media(max-width:768px){.main-image-card{max-width:130px}}.main-motion-card{max-width:100%;display:block;border-radius:8px}.main-banner-image-card{display:block;width:100%;max-height:400px;object-fit:cover;border-radius:8px}.remove-sticker{position:absolute;top:5px;right:5px}.assets-container{position:relative;min-height:60px}.assets-card{border:1px dashed rgba(12,19,142,.1215686275);padding:4px;border-radius:15px}.upload-buttons{display:flex;gap:10px}.preview-container{position:relative;margin-bottom:100px}.stickers-container{display:flex;flex-wrap:wrap;gap:10px}.sticker-wrapper{position:relative}.motion-container{position:absolute;bottom:-100px;right:20px;z-index:1;box-shadow:0 4px 8px #0003;max-width:220px;border-radius:8px;overflow:hidden}@media(max-width:1300px){.motion-container{max-width:170px}}@media(max-width:768px){.motion-container{max-width:130px}}.remove-main-motion-button{position:absolute;top:10px;right:10px;z-index:2}.motions-container{display:flex;flex-wrap:wrap;gap:10px;margin-top:20px}.motion-wrapper{position:relative;width:150px;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px #0000001a}.motion-wrapper video{min-height:220px;display:block;background-color:#f0f0f0}.remove-motion-button{position:absolute;top:5px;right:5px;z-index:2}\n"] }]
|
|
1370
|
+
}], propDecorators: { assets: [{ type: i0.Input, args: [{ isSignal: true, alias: "assets", required: true }] }], storagePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "storagePath", required: true }] }], assetsChange: [{ type: i0.Output, args: ["assetsChange"] }], assetUpdate: [{ type: i0.Output, args: ["assetUpdate"] }], onFileSelected: [{ type: i0.Output, args: ["onFileSelected"] }] } });
|
|
1073
1371
|
|
|
1074
1372
|
/*
|
|
1075
1373
|
* Public API Surface of storage-uploader
|
|
@@ -1079,5 +1377,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
|
|
|
1079
1377
|
* Generated bundle index. Do not edit.
|
|
1080
1378
|
*/
|
|
1081
1379
|
|
|
1082
|
-
export { AllAspectRatioOptions, AspectRatio, AspectRatioOptions, AspectType, AssetsLoaderComponent, CropperComponent, CropperComponentModal, DCFilesCacheService, DEFAULT_SETTINGS, ImageStoragePreviewComponent, MultiImagesStorageService, MultiObjectStorageService, ResolutionType, SafeHtmlPipe, SimpleUploaderComponent, extractBucket, extractPath };
|
|
1380
|
+
export { AllAspectRatioOptions, AspectRatio, AspectRatioOptions, AspectType, AssetsLoaderComponent, BackendUploadComponent, CropperComponent, CropperComponentModal, DCFilesCacheService, DEFAULT_SETTINGS, ImageStoragePreviewComponent, MultiImagesStorageService, MultiObjectStorageService, ResolutionType, STORAGE_PROVIDER_TYPE, SafeHtmlPipe, SimpleUploaderComponent, UniversalStorageService, extractBucket, extractPath };
|
|
1083
1381
|
//# sourceMappingURL=dataclouder-ngx-cloud-storage.mjs.map
|