@dataclouder/ngx-cloud-storage 0.0.34 → 0.0.35
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,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Injectable, input, output, ViewChild, Component, Pipe, ChangeDetectorRef, Input,
|
|
2
|
+
import { inject, Injectable, input, output, ViewChild, Component, Pipe, ChangeDetectorRef, Input, InjectionToken, signal, 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';
|
|
@@ -18,7 +18,7 @@ import * as i7 from 'primeng/select';
|
|
|
18
18
|
import { SelectModule } from 'primeng/select';
|
|
19
19
|
import * as i8 from 'primeng/inputtext';
|
|
20
20
|
import { InputTextModule } from 'primeng/inputtext';
|
|
21
|
-
import { MoodStateOptions,
|
|
21
|
+
import { MoodStateOptions, APP_CONFIG, CharacterEventActions } from '@dataclouder/ngx-core';
|
|
22
22
|
import * as i1$1 from '@angular/platform-browser';
|
|
23
23
|
import * as i3 from 'primeng/api';
|
|
24
24
|
import * as i1$2 from '@angular/common';
|
|
@@ -702,14 +702,206 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
702
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"] }]
|
|
703
703
|
}], ctorParameters: () => [], propDecorators: { imageSelected: [{ type: i0.Output, args: ["imageSelected"] }] } });
|
|
704
704
|
|
|
705
|
+
class FirebaseStorageProvider {
|
|
706
|
+
constructor() {
|
|
707
|
+
this.storage = inject(AngularFireStorage);
|
|
708
|
+
}
|
|
709
|
+
async uploadImage(image, path, provider) {
|
|
710
|
+
try {
|
|
711
|
+
const refStorage = this.storage.ref(path);
|
|
712
|
+
const task = await refStorage.put(image);
|
|
713
|
+
const url = await lastValueFrom(refStorage.getDownloadURL());
|
|
714
|
+
return {
|
|
715
|
+
url,
|
|
716
|
+
name: task.metadata.name,
|
|
717
|
+
type: task.metadata.contentType,
|
|
718
|
+
size: task.metadata.size,
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
catch (error) {
|
|
722
|
+
console.error('Firebase upload image error:', error);
|
|
723
|
+
return null;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
async uploadGenericFile(file, storagePath, metadata, keepOriginalName, provider) {
|
|
727
|
+
try {
|
|
728
|
+
const fileName = keepOriginalName ? file.name : `${Date.now()}-${file.name}`;
|
|
729
|
+
const fullFilePath = `${storagePath.replace(/\/$/, '')}/${fileName}`;
|
|
730
|
+
const refStorage = this.storage.ref(fullFilePath);
|
|
731
|
+
const task = await refStorage.put(file, { customMetadata: metadata });
|
|
732
|
+
const url = await lastValueFrom(refStorage.getDownloadURL());
|
|
733
|
+
return {
|
|
734
|
+
url,
|
|
735
|
+
name: file.name,
|
|
736
|
+
type: file.type,
|
|
737
|
+
size: file.size,
|
|
738
|
+
metadata: task.metadata,
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
catch (error) {
|
|
742
|
+
console.error('Firebase upload generic file error:', error);
|
|
743
|
+
return null;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
async uploadMultipleFiles(files, storagePath, metadata, keepOriginalName, provider) {
|
|
747
|
+
try {
|
|
748
|
+
const uploadPromises = files.map(file => this.uploadGenericFile(file, storagePath, metadata, keepOriginalName));
|
|
749
|
+
const results = await Promise.all(uploadPromises);
|
|
750
|
+
return results.filter((r) => r !== null);
|
|
751
|
+
}
|
|
752
|
+
catch (error) {
|
|
753
|
+
console.error('Firebase upload multiple files error:', error);
|
|
754
|
+
return null;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
async deleteImage(imagePath) {
|
|
758
|
+
const storageRef = this.storage.ref(imagePath);
|
|
759
|
+
await lastValueFrom(storageRef.delete());
|
|
760
|
+
}
|
|
761
|
+
async deleteDirectory(directoryPath) {
|
|
762
|
+
const storage = getStorage();
|
|
763
|
+
const directoryRef = ref(storage, directoryPath);
|
|
764
|
+
const res = await listAll(directoryRef);
|
|
765
|
+
const promises = res.items.map((itemRef) => deleteObject(itemRef));
|
|
766
|
+
await Promise.all(promises);
|
|
767
|
+
}
|
|
768
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: FirebaseStorageProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
769
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: FirebaseStorageProvider, providedIn: 'root' }); }
|
|
770
|
+
}
|
|
771
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: FirebaseStorageProvider, decorators: [{
|
|
772
|
+
type: Injectable,
|
|
773
|
+
args: [{
|
|
774
|
+
providedIn: 'root',
|
|
775
|
+
}]
|
|
776
|
+
}] });
|
|
777
|
+
|
|
778
|
+
class BackendStorageProvider {
|
|
779
|
+
constructor() {
|
|
780
|
+
this.http = inject(HttpClient);
|
|
781
|
+
this.appConfig = inject(APP_CONFIG);
|
|
782
|
+
this.apiUrl = this.appConfig.backendNodeUrl + '/storage'; // This should ideally come from an environment config
|
|
783
|
+
}
|
|
784
|
+
async uploadImage(image, path, provider = 'GOOGLE') {
|
|
785
|
+
const formData = new FormData();
|
|
786
|
+
formData.append('file', image, 'image.webp');
|
|
787
|
+
const params = {
|
|
788
|
+
path,
|
|
789
|
+
provider
|
|
790
|
+
};
|
|
791
|
+
try {
|
|
792
|
+
return await firstValueFrom(this.http.post(`${this.apiUrl}/upload`, formData, { params }));
|
|
793
|
+
}
|
|
794
|
+
catch (error) {
|
|
795
|
+
console.error('Backend upload image error:', error);
|
|
796
|
+
return null;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
async uploadGenericFile(file, storagePath, metadata, keepOriginalName, provider = 'GOOGLE') {
|
|
800
|
+
const formData = new FormData();
|
|
801
|
+
if (metadata) {
|
|
802
|
+
formData.append('metadata', JSON.stringify(metadata));
|
|
803
|
+
}
|
|
804
|
+
formData.append('file', file);
|
|
805
|
+
const params = {
|
|
806
|
+
path: storagePath,
|
|
807
|
+
provider
|
|
808
|
+
};
|
|
809
|
+
if (keepOriginalName) {
|
|
810
|
+
params.keepOriginalName = 'true';
|
|
811
|
+
}
|
|
812
|
+
try {
|
|
813
|
+
return await firstValueFrom(this.http.post(`${this.apiUrl}/upload`, formData, { params }));
|
|
814
|
+
}
|
|
815
|
+
catch (error) {
|
|
816
|
+
console.error('Backend upload generic file error:', error);
|
|
817
|
+
return null;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
async uploadMultipleFiles(files, storagePath, metadata, keepOriginalName, provider = 'GOOGLE') {
|
|
821
|
+
const formData = new FormData();
|
|
822
|
+
if (metadata) {
|
|
823
|
+
formData.append('metadata', JSON.stringify(metadata));
|
|
824
|
+
}
|
|
825
|
+
files.forEach(file => {
|
|
826
|
+
formData.append('file', file, file.name);
|
|
827
|
+
});
|
|
828
|
+
const params = {
|
|
829
|
+
path: storagePath,
|
|
830
|
+
provider
|
|
831
|
+
};
|
|
832
|
+
if (keepOriginalName) {
|
|
833
|
+
params.keepOriginalName = 'true';
|
|
834
|
+
}
|
|
835
|
+
try {
|
|
836
|
+
return await firstValueFrom(this.http.post(`${this.apiUrl}/upload-multiple`, formData, { params }));
|
|
837
|
+
}
|
|
838
|
+
catch (error) {
|
|
839
|
+
console.error('Backend upload multiple files error:', error);
|
|
840
|
+
return null;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
async deleteImage(imagePath) {
|
|
844
|
+
// Implement delete if the backend controller supports it
|
|
845
|
+
console.warn('Backend delete image not implemented yet');
|
|
846
|
+
}
|
|
847
|
+
async deleteDirectory(directoryPath) {
|
|
848
|
+
// Implement delete directory if the backend controller supports it
|
|
849
|
+
console.warn('Backend delete directory not implemented yet');
|
|
850
|
+
}
|
|
851
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: BackendStorageProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
852
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: BackendStorageProvider, providedIn: 'root' }); }
|
|
853
|
+
}
|
|
854
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: BackendStorageProvider, decorators: [{
|
|
855
|
+
type: Injectable,
|
|
856
|
+
args: [{
|
|
857
|
+
providedIn: 'root',
|
|
858
|
+
}]
|
|
859
|
+
}] });
|
|
860
|
+
|
|
861
|
+
const STORAGE_PROVIDER_TYPE = new InjectionToken('STORAGE_PROVIDER_TYPE');
|
|
862
|
+
class UniversalStorageService {
|
|
863
|
+
constructor() {
|
|
864
|
+
this.firebaseProvider = inject(FirebaseStorageProvider);
|
|
865
|
+
this.backendProvider = inject(BackendStorageProvider);
|
|
866
|
+
this.providerType = inject(STORAGE_PROVIDER_TYPE, { optional: true }) || 'FIREBASE';
|
|
867
|
+
}
|
|
868
|
+
get provider() {
|
|
869
|
+
return this.providerType === 'BACKEND' ? this.backendProvider : this.firebaseProvider;
|
|
870
|
+
}
|
|
871
|
+
async uploadImage(image, path, provider) {
|
|
872
|
+
return this.provider.uploadImage(image, path, provider);
|
|
873
|
+
}
|
|
874
|
+
uploadGenericFile(file, storagePath, metadata, keepOriginalName, provider) {
|
|
875
|
+
return this.provider.uploadGenericFile(file, storagePath, metadata, keepOriginalName, provider);
|
|
876
|
+
}
|
|
877
|
+
uploadMultipleFiles(files, storagePath, metadata, keepOriginalName, provider) {
|
|
878
|
+
return this.provider.uploadMultipleFiles(files, storagePath, metadata, keepOriginalName, provider);
|
|
879
|
+
}
|
|
880
|
+
async deleteImage(imagePath) {
|
|
881
|
+
return this.provider.deleteImage(imagePath);
|
|
882
|
+
}
|
|
883
|
+
async deleteDirectory(directoryPath) {
|
|
884
|
+
return this.provider.deleteDirectory(directoryPath);
|
|
885
|
+
}
|
|
886
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: UniversalStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
887
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: UniversalStorageService, providedIn: 'root' }); }
|
|
888
|
+
}
|
|
889
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: UniversalStorageService, decorators: [{
|
|
890
|
+
type: Injectable,
|
|
891
|
+
args: [{
|
|
892
|
+
providedIn: 'root',
|
|
893
|
+
}]
|
|
894
|
+
}] });
|
|
895
|
+
|
|
705
896
|
class SimpleUploaderComponent {
|
|
706
897
|
constructor() {
|
|
707
|
-
this.
|
|
898
|
+
this.universalStorageService = inject(UniversalStorageService);
|
|
708
899
|
this.storagePath = input.required(...(ngDevMode ? [{ debugName: "storagePath" }] : []));
|
|
709
900
|
this.buttonLabel = input('Upload File', ...(ngDevMode ? [{ debugName: "buttonLabel" }] : []));
|
|
710
901
|
this.accept = input('*/*', ...(ngDevMode ? [{ debugName: "accept" }] : []));
|
|
711
902
|
this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
712
903
|
this.metadata = input({}, ...(ngDevMode ? [{ debugName: "metadata" }] : []));
|
|
904
|
+
this.provider = input('GOOGLE', ...(ngDevMode ? [{ debugName: "provider" }] : []));
|
|
713
905
|
this.fileUploaded = output();
|
|
714
906
|
this.uploadError = output();
|
|
715
907
|
this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
@@ -749,9 +941,9 @@ class SimpleUploaderComponent {
|
|
|
749
941
|
event: this.eventSelected(),
|
|
750
942
|
};
|
|
751
943
|
try {
|
|
752
|
-
const result = await this.
|
|
753
|
-
result.metadata = metadata;
|
|
944
|
+
const result = await this.universalStorageService.uploadGenericFile(file, this.storagePath(), metadata, false, this.provider());
|
|
754
945
|
if (result) {
|
|
946
|
+
result.metadata = metadata;
|
|
755
947
|
this.fileUploaded.emit(result);
|
|
756
948
|
}
|
|
757
949
|
else {
|
|
@@ -772,12 +964,12 @@ class SimpleUploaderComponent {
|
|
|
772
964
|
}
|
|
773
965
|
}
|
|
774
966
|
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"] }] }); }
|
|
967
|
+
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 }, provider: { classPropertyName: "provider", publicName: "provider", 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"] }] }); }
|
|
776
968
|
}
|
|
777
969
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: SimpleUploaderComponent, decorators: [{
|
|
778
970
|
type: Component,
|
|
779
971
|
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" }]
|
|
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"] }] } });
|
|
972
|
+
}], 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 }] }], provider: [{ type: i0.Input, args: [{ isSignal: true, alias: "provider", required: false }] }], fileUploaded: [{ type: i0.Output, args: ["fileUploaded"] }], uploadError: [{ type: i0.Output, args: ["uploadError"] }] } });
|
|
781
973
|
|
|
782
974
|
class DCFilesCacheService {
|
|
783
975
|
constructor() {
|
|
@@ -923,203 +1115,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
923
1115
|
}]
|
|
924
1116
|
}] });
|
|
925
1117
|
|
|
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' }); }
|
|
1074
|
-
}
|
|
1075
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: BackendStorageProvider, decorators: [{
|
|
1076
|
-
type: Injectable,
|
|
1077
|
-
args: [{
|
|
1078
|
-
providedIn: 'root',
|
|
1079
|
-
}]
|
|
1080
|
-
}] });
|
|
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
1118
|
class BackendUploadComponent {
|
|
1118
1119
|
constructor() {
|
|
1119
1120
|
this.storageService = inject(UniversalStorageService);
|
|
1120
1121
|
this.onUploadFinish = new EventEmitter();
|
|
1121
1122
|
this.storagePath = 'test-uploads';
|
|
1122
1123
|
this.keepOriginalNames = true;
|
|
1124
|
+
this.provider = 'GOOGLE';
|
|
1123
1125
|
this.uploading = signal(false, ...(ngDevMode ? [{ debugName: "uploading" }] : []));
|
|
1124
1126
|
this.status = signal(null, ...(ngDevMode ? [{ debugName: "status" }] : []));
|
|
1125
1127
|
this.message = signal('', ...(ngDevMode ? [{ debugName: "message" }] : []));
|
|
@@ -1152,7 +1154,7 @@ class BackendUploadComponent {
|
|
|
1152
1154
|
groupedFiles[uploadPath].push(file);
|
|
1153
1155
|
});
|
|
1154
1156
|
const uploadPromises = Object.entries(groupedFiles).map(([path, pathFiles]) => {
|
|
1155
|
-
return this.storageService.uploadMultipleFiles(pathFiles, path, null, this.keepOriginalNames);
|
|
1157
|
+
return this.storageService.uploadMultipleFiles(pathFiles, path, null, this.keepOriginalNames, this.provider);
|
|
1156
1158
|
});
|
|
1157
1159
|
const results = await Promise.all(uploadPromises);
|
|
1158
1160
|
const flattenedResults = results.flat().filter(result => result && result.url);
|
|
@@ -1222,7 +1224,7 @@ class BackendUploadComponent {
|
|
|
1222
1224
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
|
1223
1225
|
}
|
|
1224
1226
|
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: [
|
|
1227
|
+
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", provider: "provider" }, outputs: { onUploadFinish: "onUploadFinish" }, providers: [
|
|
1226
1228
|
{ provide: STORAGE_PROVIDER_TYPE, useValue: 'BACKEND' },
|
|
1227
1229
|
UniversalStorageService
|
|
1228
1230
|
], 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"] }] }); }
|
|
@@ -1242,6 +1244,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
1242
1244
|
type: Input
|
|
1243
1245
|
}], keepOriginalNames: [{
|
|
1244
1246
|
type: Input
|
|
1247
|
+
}], provider: [{
|
|
1248
|
+
type: Input
|
|
1245
1249
|
}] } });
|
|
1246
1250
|
|
|
1247
1251
|
class AssetsLoaderComponent {
|
|
@@ -1362,7 +1366,7 @@ class AssetsLoaderComponent {
|
|
|
1362
1366
|
}
|
|
1363
1367
|
}
|
|
1364
1368
|
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"] }] }); }
|
|
1369
|
+
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", "provider"], 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"] }] }); }
|
|
1366
1370
|
}
|
|
1367
1371
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AssetsLoaderComponent, decorators: [{
|
|
1368
1372
|
type: Component,
|