diff --git a/src/app/pages/agenda/agenda.page.html b/src/app/pages/agenda/agenda.page.html index 785c0c195..68412c638 100644 --- a/src/app/pages/agenda/agenda.page.html +++ b/src/app/pages/agenda/agenda.page.html @@ -395,6 +395,7 @@ [adding]="adding" [taskParticipants]="taskParticipants" [taskParticipantsCc]="taskParticipantsCc" + [hideExternalDomain]="false" (setIntervenient)="setIntervenient($event)" (setIntervenientCC)="setIntervenientCC($event)" > diff --git a/src/app/pages/agenda/new-event/new-event.page.ts b/src/app/pages/agenda/new-event/new-event.page.ts index be62eead5..35a51d0a9 100644 --- a/src/app/pages/agenda/new-event/new-event.page.ts +++ b/src/app/pages/agenda/new-event/new-event.page.ts @@ -97,7 +97,7 @@ export class NewEventPage implements OnInit { environment = environment eventPersons: EventPerson[]; contacts: EventPerson[]; - + constructor( private modalController: ModalController, @@ -552,6 +552,7 @@ export class NewEventPage implements OnInit { const modal = await this.modalController.create({ component: AttendeesPageModal, componentProps: { + hideExternalDomain: false, adding: this.adding, taskParticipants: this.taskParticipants, taskParticipantsCc: this.taskParticipantsCc diff --git a/src/app/pages/events/attendees/attendees.page.ts b/src/app/pages/events/attendees/attendees.page.ts index 5f6245388..a00eaeefe 100644 --- a/src/app/pages/events/attendees/attendees.page.ts +++ b/src/app/pages/events/attendees/attendees.page.ts @@ -26,6 +26,7 @@ export class AttendeesPageModal implements OnInit { taskParticipantsCc:EventPerson[] = []; loggeduser: LoginUserRespose; @Input() loggedAttendSon: boolean; + hideExternalDomain = true; taskType: any; @@ -41,6 +42,7 @@ export class AttendeesPageModal implements OnInit { this.taskParticipants = this.navParams.get('taskParticipants'); this.taskParticipantsCc = this.navParams.get('taskParticipantsCc'); this.taskType = this.navParams.get('taskType'); + this.hideExternalDomain = this.navParams.get('hideExternalDomain'); this.loggeduser = SessionStore.user; @@ -134,8 +136,15 @@ export class AttendeesPageModal implements OnInit { async fetchContacts(filter: string) { this.showLoader = true; - this.contactsService.getContacts(filter).subscribe(result => - { + this.contactsService.getContacts(filter).subscribe(_result => { + + let result + if(this.hideExternalDomain) { + result = _result.filter( e => e.UserType == 'GD') + } else { + result = _result + } + if (this.eventPersons != null) { this.eventPersons.forEach(attendee => { diff --git a/src/app/pages/events/edit-event/edit-event.page.ts b/src/app/pages/events/edit-event/edit-event.page.ts index c65f80a44..66ea7f577 100644 --- a/src/app/pages/events/edit-event/edit-event.page.ts +++ b/src/app/pages/events/edit-event/edit-event.page.ts @@ -72,7 +72,7 @@ export class EditEventPage implements OnInit { else{ this.pageId = paramMap.get('eventId'); eventid = paramMap.get('eventId'); - + } if (paramMap.has("caller")){ @@ -89,6 +89,7 @@ export class EditEventPage implements OnInit { const modal = await this.modalCtrl.create({ component: AttendeesPageModal, componentProps: { + hideExternalDomain: false, eventAttendees: this.loadedEvent.Attendees }, cssClass: 'attendee modal-desktop', @@ -165,7 +166,7 @@ export class EditEventPage implements OnInit { this.activatedRoute.paramMap.subscribe(paramMap =>{ if (paramMap.has("profile")){ - + } }); @@ -193,7 +194,7 @@ export class EditEventPage implements OnInit { { this.attachamentsService.getAttachmentsById(this.pageId).subscribe(res => { this.loadedEventAttachments = res; - + },((erro) => { console.error('loadAttchament', erro) diff --git a/src/app/services/events/attendees/attendees.page.ts b/src/app/services/events/attendees/attendees.page.ts index 7d7caf12b..1d79c6b31 100644 --- a/src/app/services/events/attendees/attendees.page.ts +++ b/src/app/services/events/attendees/attendees.page.ts @@ -26,6 +26,7 @@ export class AttendeesPageModal implements OnInit { taskParticipantsCc:EventPerson[] = []; loggeduser: LoginUserRespose; @Input() loggedAttendSon: boolean; + @Input() hideExternalDomain = true; taskType: any; @@ -133,8 +134,17 @@ export class AttendeesPageModal implements OnInit { async fetchContacts(filter: string) { this.showLoader = true; - this.contactsService.getContacts(filter).subscribe(result => + this.contactsService.getContacts(filter).subscribe(_result => { + + let result + if(this.hideExternalDomain) { + result = _result.filter( e => e.UserType == 'GD') + } else { + result = _result + } + + if (this.eventPersons != null) { this.eventPersons.forEach(attendee => { diff --git a/src/app/services/http/http-service.service.ts b/src/app/services/http/http-service.service.ts index 544cf08b8..2bde9e63d 100644 --- a/src/app/services/http/http-service.service.ts +++ b/src/app/services/http/http-service.service.ts @@ -11,41 +11,17 @@ export class HttpServiceService { constructor(private http: HttpClient) {} - put(url: string, body: any | null, options: Options): Observable { - return this.http.put(url, body, options as any).pipe( - tap((response) => { - // Handle success response if needed - }), - catchError((error) => { - // Handle error response if needed - return of(error); - }) - ); + put(url: string, body: any | null, options: Options) { + return this.http.put(url, body, options as any) } - post(url: string, body: any | null, options: Options): Observable { - return this.http.post(url, body, options as any).pipe( - tap((response) => { - // Handle success response if needed - }), - catchError((error) => { - // Handle error response if needed - return of(error); - }) - ); + post(url: string, body: any | null, options: Options) { + return this.http.post(url, body, options as any) } - get(url: string, options: Options): Observable { - return this.http.get(url, options ).pipe( - tap((response) => { - // Handle success response if needed - }), - catchError((error) => { - // Handle error response if needed - return of(error); - }) - ); + get(url: string, options: Options) { + return this.http.get(url, options ) } } diff --git a/src/app/shared/API/middleware/middleware-service.service.ts b/src/app/shared/API/middleware/middleware-service.service.ts index cb091cfaa..c7271b40b 100644 --- a/src/app/shared/API/middleware/middleware-service.service.ts +++ b/src/app/shared/API/middleware/middleware-service.service.ts @@ -3,7 +3,7 @@ import { environment } from 'src/environments/environment'; import { HttpServiceService } from 'src/app/services/http/http-service.service'; import { Observable} from 'rxjs'; import { CreateEvent, EditEvent, EventDetailsDTO, EventsDTO, refreshTokenDTO } from "./interface"; -import { HttpParams } from '@angular/common/http'; +import { HttpHeaders, HttpParams } from '@angular/common/http'; import { DetectCalendars, makeHeaderForCalendar } from '../../utils/utils'; import { z } from "zod"; import { ok, err } from 'neverthrow'; @@ -18,14 +18,16 @@ export class MiddlewareServiceService { constructor( private HttpServiceService: HttpServiceService, - ) {} + ) { + window["MiddlewareServiceService"] = this + } - refreshToken(refreshToken: string): Observable { + refreshToken(refreshToken: string){ const data = { refreshToken: refreshToken } - return this.HttpServiceService.put(environment.apiURL + "UserAuthentication/RefreshToken", data, {}) + return this.HttpServiceService.put(environment.apiURL + "UserAuthentication/RefreshToken", data, {}) // .pipe( // map((response: HttpResponse) => { // return response.body @@ -134,4 +136,22 @@ export class MiddlewareServiceService { } // ================================ Acções ================================================= + + + // ========== LKFRT + + uploadFileLK(formData: FormData) { + + const headers = new HttpHeaders(); + headers.set('Authorization', 'Bearer ' + SessionStore.user.Authorization); + + //const geturl = environment.apiURL + 'Tasks/DelegateTask'; + const geturl = environment.apiURL + 'ObjectServer/UploadFiles'; + + let options = { + headers: headers + }; + + return this.HttpServiceService.post(`${geturl}`, formData, options); + } } diff --git a/src/app/shared/event/attendee-modal/attendee-modal.page.ts b/src/app/shared/event/attendee-modal/attendee-modal.page.ts index f865506d0..3e5c8d5a0 100644 --- a/src/app/shared/event/attendee-modal/attendee-modal.page.ts +++ b/src/app/shared/event/attendee-modal/attendee-modal.page.ts @@ -32,6 +32,9 @@ export class AttendeePage implements OnInit { @Output() dynamicSetIntervenient = new EventEmitter(); + @Input() hideExternalDomain = true; + + @Input() taskParticipants: EventPerson[] = []; @Input() taskParticipantsCc: EventPerson[] = []; @Input() loggedAttendSon: boolean; @@ -231,7 +234,15 @@ export class AttendeePage implements OnInit { async fetchContacts(filter: string) { this.showLoader = true; - this.contactsService.getContacts(filter).subscribe(result => { + this.contactsService.getContacts(filter).subscribe(_result => { + + let result + if(this.hideExternalDomain) { + result = _result.filter( e => e.UserType == 'GD') + } else { + result = _result + } + if (this.eventPersons != null) { this.eventPersons.forEach(attendee => { const index: number = result.findIndex((cont) => { diff --git a/src/app/shared/publication/new-publication/ModelView/model/publication-attachment-entity.service.spec.ts b/src/app/shared/publication/new-publication/ModelView/model/publication-attachment-entity.service.spec.ts new file mode 100644 index 000000000..c5f0d8a20 --- /dev/null +++ b/src/app/shared/publication/new-publication/ModelView/model/publication-attachment-entity.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { PublicationAttachmentEntityService } from './publication-attachment-entity.service'; + +describe('PublicationAttachmentEntityService', () => { + let service: PublicationAttachmentEntityService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(PublicationAttachmentEntityService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/shared/publication/new-publication/ModelView/model/publication-attachment-entity.service.ts b/src/app/shared/publication/new-publication/ModelView/model/publication-attachment-entity.service.ts new file mode 100644 index 000000000..a316a1da3 --- /dev/null +++ b/src/app/shared/publication/new-publication/ModelView/model/publication-attachment-entity.service.ts @@ -0,0 +1,31 @@ + +export class PublicationAttachmentEntityService { + FileBase64: string + FileExtension: string + FileType: 'image' | 'video' + OriginalFileName: string + blob: any + + constructor({base64, extension, blob = null, OriginalFileName = null, FileType}) { + this.FileBase64 = base64; + this.FileExtension = extension; + this.blob = blob + this.OriginalFileName = OriginalFileName + this.FileType = FileType + + this.fixFileBase64(); + } + + fixFileBase64() { + if(this.FileType == 'image' ) { + if(!this.FileBase64.startsWith('data:')) { + this.FileBase64 = 'data:image/jpg;base64,' + this.FileBase64 + } + } else if (this.FileType == 'video' ) { + if(!this.FileBase64.startsWith('data:')) { + this.FileBase64 = 'data:video/mp4;base64,' + this.FileBase64 + } + + } + } +} diff --git a/src/app/shared/publication/new-publication/ModelView/model/publication-form-model.service.spec.ts b/src/app/shared/publication/new-publication/ModelView/model/publication-form-model.service.spec.ts new file mode 100644 index 000000000..a3044b707 --- /dev/null +++ b/src/app/shared/publication/new-publication/ModelView/model/publication-form-model.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { PublicationFormModelService } from './publication-form-model.service'; + +describe('PublicationFormModelService', () => { + let service: PublicationFormModelService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(PublicationFormModelService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/shared/publication/new-publication/ModelView/model/publication-form-model.service.ts b/src/app/shared/publication/new-publication/ModelView/model/publication-form-model.service.ts new file mode 100644 index 000000000..120135d00 --- /dev/null +++ b/src/app/shared/publication/new-publication/ModelView/model/publication-form-model.service.ts @@ -0,0 +1,22 @@ +import { Injectable } from '@angular/core'; +import { IPublicationFormModelEntity } from '../../interface/interface'; +import { PublicationAttachmentEntityService } from "./publication-attachment-entity.service" + +@Injectable({ + providedIn: 'root' +}) +export class PublicationFormModelService { + constructor() {} + DateIndex: any; + DocumentId: any; + ProcessId: any; + Title: any; + Message: any; + DatePublication: any; + OriginalFileName: string; + Files: PublicationAttachmentEntityService[]; + + setData(data: IPublicationFormModelEntity) { + Object.assign(this, data) + } +} diff --git a/src/app/shared/publication/new-publication/ModelView/publication-from-mv.service.spec.ts b/src/app/shared/publication/new-publication/ModelView/publication-from-mv.service.spec.ts new file mode 100644 index 000000000..17cfed92b --- /dev/null +++ b/src/app/shared/publication/new-publication/ModelView/publication-from-mv.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { PublicationFromMVService } from './publication-from-mv.service'; + +describe('PublicationFromMVService', () => { + let service: PublicationFromMVService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(PublicationFromMVService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/shared/publication/new-publication/ModelView/publication-from-mv.service.ts b/src/app/shared/publication/new-publication/ModelView/publication-from-mv.service.ts new file mode 100644 index 000000000..efb318e03 --- /dev/null +++ b/src/app/shared/publication/new-publication/ModelView/publication-from-mv.service.ts @@ -0,0 +1,39 @@ +import { Injectable } from '@angular/core'; +import { UploadFileUserCaseService } from "src/app/shared/publication/new-publication/usercase/upload-file-user-case.service" +import { IPublicationFormModelEntity } from '../interface/interface'; +import { PublicationFormModelService } from "./model/publication-form-model.service" +import { PublicationAttachmentEntityService } from './model/publication-attachment-entity.service'; +@Injectable({ + providedIn: 'root' +}) +export class PublicationFromMVService { + + constructor( + public UploadFileUserCaseService: UploadFileUserCaseService, + public form: PublicationFormModelService) {} + + setDataToFrom(data: IPublicationFormModelEntity) { + this.form.setData(data) + } + + private getVideoFiles() { + return this.form.Files.filter( x => x.FileType == 'video') + } + + private async upload(PublicationAttachmentEntity: PublicationAttachmentEntityService) { + + console.log(PublicationAttachmentEntity) + this.UploadFileUserCaseService.execute(PublicationAttachmentEntity) + } + + uploadVideosFiles() { + + const videosFiles = this.getVideoFiles() + + console.log(this.form) + + for(const file of videosFiles) { + this.upload(file) + } + } +} diff --git a/src/app/shared/publication/new-publication/interface/interface.d.ts b/src/app/shared/publication/new-publication/interface/interface.d.ts new file mode 100644 index 000000000..4524c3788 --- /dev/null +++ b/src/app/shared/publication/new-publication/interface/interface.d.ts @@ -0,0 +1,18 @@ +export interface IPublicationFormModelEntity { + DateIndex: any + DocumentId: any + ProcessId: any + Title: any + Message: any + DatePublication: any + Files: PublicationAttachmentEntity[] +} + + +export class IPublicationAttachmentEntity { + FileBase64: string + FileExtension: string + FileType: 'image' | 'video' + OriginalFileName: string + blob: any +} diff --git a/src/app/shared/publication/new-publication/new-publication.page.html b/src/app/shared/publication/new-publication/new-publication.page.html index c0b483a19..63ca8ff55 100644 --- a/src/app/shared/publication/new-publication/new-publication.page.html +++ b/src/app/shared/publication/new-publication/new-publication.page.html @@ -47,18 +47,20 @@ + + name="image" ngDefaultControl [src]="seleted.FileBase64"> + -

mais {{ seletedContent.length - displayLimit }}

diff --git a/src/app/shared/publication/new-publication/new-publication.page.ts b/src/app/shared/publication/new-publication/new-publication.page.ts index 33d321d2b..ac83ec3d2 100644 --- a/src/app/shared/publication/new-publication/new-publication.page.ts +++ b/src/app/shared/publication/new-publication/new-publication.page.ts @@ -1,8 +1,6 @@ import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; -import { SafeResourceUrl } from '@angular/platform-browser'; import { PublicationsService } from 'src/app/services/publications.service'; import { Publication } from 'src/app/models/publication'; -import { Image } from 'src/app/models/image'; import { PhotoService } from 'src/app/services/photo.service'; import { ToastService } from 'src/app/services/toast.service'; import { FormControl, FormGroup, Validators } from '@angular/forms'; @@ -11,10 +9,17 @@ import { Camera, CameraResultType, CameraSource } from '@capacitor/camera'; import { HttpErrorHandle } from 'src/app/services/http-error-handle.service'; import { PublicationFolderService } from 'src/app/store/publication-folder.service'; import { FilePicker } from '@capawesome/capacitor-file-picker'; -import { Directory, Encoding, Filesystem } from '@capacitor/filesystem'; -import { utf8Encode } from '@angular/compiler/src/util'; import { checkFileTypeService } from 'src/app/services/checkFileType.service'; import { FileValidatorService } from "src/app/services/file/file-validator.service" +import { MiddlewareServiceService } from "src/app/shared/API/middleware/middleware-service.service" +import { LakefsRepositoryService } from '../../repository/lakefs/lakefs-repository.service'; + + +enum ActionType { + newRapid = "1", + new = "2", + edit = "3" +} @Component({ selector: 'app-new-publication', @@ -33,7 +38,6 @@ export class NewPublicationPage implements OnInit { Form: FormGroup; validateFrom = false - @Input() publication!: Publication; @Input() publicationType: string; @Input() folderId: string; @@ -51,10 +55,13 @@ export class NewPublicationPage implements OnInit { fileType: string; filecontent: boolean; captureContent: any; - seletedContent: any[] = [] + seletedContent: PublicationAttachmentEntity[] = [] displayLimit = 4; filesSizeSum = 0; + + publicationFormMV = new PublicationFormMV() + constructor( public photoService: PhotoService, private publications: PublicationsService, @@ -63,16 +70,16 @@ export class NewPublicationPage implements OnInit { private httpErroHandle: HttpErrorHandle, public PublicationFolderService: PublicationFolderService, public checkFileType: checkFileTypeService, - private FileValidatorService: FileValidatorService + private FileValidatorService: FileValidatorService, + private MiddlewareServiceService: MiddlewareServiceService, + private LakefsRepositoryService: LakefsRepositoryService ) { this.publicationTitle = 'Nova Publicação'; - + if (this.publication) { this.seletedContent = this.publication.Files; this.filecontent = true; } - - } ngOnInit() { @@ -93,7 +100,6 @@ export class NewPublicationPage implements OnInit { this.setData() } - setData() { if (!this.publicationType) { setTimeout(() => { @@ -106,10 +112,9 @@ export class NewPublicationPage implements OnInit { } } - getPublicationDetail() { console.log('edit 1', this.publicationType) - if (this.publicationType != '2') { + if (this.publicationType != ActionType.new) { this.showLoader = true; this.publications.GetPublicationWithArrayOfFilesById(this.documentId).subscribe(res => { this.publication = { @@ -133,8 +138,6 @@ export class NewPublicationPage implements OnInit { this.goBack() }); } - - } async takePicture() { @@ -159,7 +162,20 @@ export class NewPublicationPage implements OnInit { FileBase64: picture, FileExtension: this.removeTextBeforeSlash('jpeg','/') } - this.seletedContent.push(fileObject) + + const FileExtension = this.removeTextBeforeSlash('jpeg','/') + + const newAttachment = new PublicationAttachmentEntity( + { + base64: picture, + extension: FileExtension, + OriginalFileName: "foto", + FileType: 'image' + } + ) + + this.seletedContent.push(newAttachment) + }); /* } else { this.toastService._badRequest("Imagem inválida") @@ -188,7 +204,19 @@ export class NewPublicationPage implements OnInit { FileBase64: picture, FileExtension: this.removeTextBeforeSlash('jpeg','/') } - this.seletedContent.push(fileObject) + + const FileExtension = this.removeTextBeforeSlash('jpeg','/') + + const newAttachment = new PublicationAttachmentEntity( + { + base64: picture, + extension: FileExtension, + OriginalFileName: "foto", + FileType: 'image' + } + ) + + this.seletedContent.push(newAttachment) }); } @@ -200,20 +228,25 @@ export class NewPublicationPage implements OnInit { multiple: true, }); - - result.files.forEach(async element => { - console.log(element) if(this.checkFileType.checkFileType(element.mimeType) == 'image' || this.checkFileType.checkFileType(element.mimeType) == 'video') { this.convertBlobToBase64(element.blob).then((value) => { - this.filesSizeSum = this.filesSizeSum + element.size + this.filesSizeSum = this.filesSizeSum + element.size if(this.fileSizeToMB(this.filesSizeSum) <= 20) { - let fileObject = { - FileBase64: value, - FileExtension: this.removeTextBeforeSlash(element.mimeType,'/') - } - this.seletedContent.push(fileObject) + + const FileExtension = this.removeTextBeforeSlash(element.mimeType,'/') + + const newAttachment = new PublicationAttachmentEntity( + { + base64: value, + extension: FileExtension, + blob: element.blob, + FileType: 'video' + } + ) + + this.seletedContent.push(newAttachment) this.filecontent = true; } else { if(this.seletedContent.length === 0) @@ -225,7 +258,7 @@ export class NewPublicationPage implements OnInit { } else { this.httpErroHandle.validationMessagge('filetype'); } - + }); /* this.capturedImage = 'data:image/jpeg;base64,' +capturedImage.base64String; @@ -282,7 +315,7 @@ export class NewPublicationPage implements OnInit { } - if (this.publicationType == '3') { + if (this.publicationType == ActionType.edit) { if (!this.publication?.OriginalFileName || !this.pub.OriginalFileName) { @@ -328,7 +361,7 @@ export class NewPublicationPage implements OnInit { } } else { - }/* + }/* else if (!this.PublicationFolderService.PublicationHasImage(this.publication)) { // this.publication = { @@ -373,27 +406,12 @@ export class NewPublicationPage implements OnInit { Files: this.seletedContent, } - const loader = this.toastService.loading() + this.publicationFormMV.setDataToFrom(this.publication) + this.publicationFormMV.uploadVideosFiles(); - try { - await this.publications.CreatePublication(this.publication.ProcessId, this.publication).toPromise() - if (this.publicationTitle == '1') { - - } else if (this.publicationTitle == '2') { - this.httpErroHandle.httpsSucessMessagge('Criar publicação') - } else if (this.publicationTitle == '3') { - this.httpErroHandle.httpsSucessMessagge('Editar publicação') - } - - this.goBackToViewPublications.emit(); - } catch (error) { - this.httpErroHandle.httpStatusHandle(error) - } finally { - loader.remove() - } } else { - + } } @@ -414,13 +432,13 @@ export class NewPublicationPage implements OnInit { } setTitle() { - if (this.publicationType == '1') { + if (this.publicationType == ActionType.newRapid) { this.publicationTitle = 'Nova Publicação Rápida'; } - else if (this.publicationType == '2') { + else if (this.publicationType == ActionType.new) { this.publicationTitle = 'Nova Publicação'; } - else if (this.publicationType == '3') { + else if (this.publicationType == ActionType.edit) { this.publicationTitle = 'Editar Publicação'; this.pub = this.publication; } @@ -428,7 +446,7 @@ export class NewPublicationPage implements OnInit { async goBack() { - if (this.publicationType == '2') { + if (this.publicationType == ActionType.new) { this.goBackToViewPublications.emit(); } else { this.goBackToViewPublications.emit(); @@ -500,55 +518,55 @@ export class NewPublicationPage implements OnInit { // Decode the base64 video string to an ArrayBuffer const trimmedBase64 = base64String.trim(); const videoBuffer = this.base64ToArrayBuffer(this.removeTextBeforeSlash(trimmedBase64, ',')); - + // Create a Blob from the ArrayBuffer const videoBlob = new Blob([videoBuffer], { type: 'video/mp4' }); - + // Create an object URL from the Blob const videoObjectUrl = URL.createObjectURL(videoBlob); - + // Create a video element const video = document.createElement('video'); video.src = videoObjectUrl; - + // Wait for the video to load metadata video.addEventListener('loadedmetadata', async () => { const canvas = document.createElement('canvas'); let newWidth = video.videoWidth; let newHeight = video.videoHeight; - + if (newWidth > maxWidth) { newHeight *= maxWidth / newWidth; newWidth = maxWidth; } - + if (newHeight > maxHeight) { newWidth *= maxHeight / newHeight; newHeight = maxHeight; } - + canvas.width = newWidth; canvas.height = newHeight; - + const context = canvas.getContext('2d'); - + // Start continuous rendering function render() { context?.drawImage(video, 0, 0, newWidth, newHeight); requestAnimationFrame(render); } - + render(); - + // Convert the canvas to a Blob canvas.toBlob(async (blob) => { if (blob) { // Read the Blob as an ArrayBuffer const compressedVideoBuffer = await this.readBlobAsArrayBuffer(blob); - + // Convert the ArrayBuffer back to base64 const compressedBase64 = this.arrayBufferToBase64(compressedVideoBuffer); - + resolve(compressedBase64); } else { reject('Error creating compressed video blob.'); @@ -560,7 +578,7 @@ export class NewPublicationPage implements OnInit { } }); } - + /* async compressVideoBase64(base64String: string, maxWidth: number, maxHeight: number, quality: number): Promise { @@ -568,147 +586,147 @@ export class NewPublicationPage implements OnInit { try { // Decode the base64 video string to an ArrayBuffer const videoBuffer = this.base64ToArrayBuffer(this.removeTextBeforeSlash(base64String,',')); - + // Create a Blob from the ArrayBuffer const videoBlob = new Blob([videoBuffer], { type: 'video/mp4' }); - + // Create an object URL from the Blob const videoObjectUrl = URL.createObjectURL(videoBlob); - + // Create a video element const video = document.createElement('video'); - + // Create a source element and set its type attribute const source = document.createElement('source'); source.type = 'video/mp4'; - + // Set the source URL source.src = videoObjectUrl; - + // Append the source element to the video element video.appendChild(source); - + // Wait for the video to load video.addEventListener('loadedmetadata', async () => { const canvas = document.createElement('canvas'); let newWidth = video.videoWidth; let newHeight = video.videoHeight; - + if (newWidth > maxWidth) { newHeight *= maxWidth / newWidth; newWidth = maxWidth; } - + if (newHeight > maxHeight) { newWidth *= maxHeight / newHeight; newHeight = maxHeight; } - + canvas.width = newWidth; canvas.height = newHeight; - + const context = canvas.getContext('2d'); - + // Create a function to draw each video frame onto the canvas const drawFrame = () => { context?.drawImage(video, 0, 0, newWidth, newHeight); - + // Convert the canvas to a Blob with the correct MIME type canvas.toBlob(async (blob) => { if (blob) { // Read the Blob as an ArrayBuffer const compressedVideoBuffer = await this.readBlobAsArrayBuffer(blob); - + // Convert the ArrayBuffer back to base64 const compressedBase64 = this.arrayBufferToBase64(compressedVideoBuffer); - + resolve(compressedBase64); } else { reject('Error creating compressed video blob.'); } }, 'video/mp4', quality); - + // Request the next video frame requestAnimationFrame(drawFrame); }; - + // Start drawing frames drawFrame(); - + // Start playing the video video.play(); }); - + } catch (error) { reject(error); } }); } */ - - + + /* async compressVideoBase64(base64String: string, maxWidth: number, maxHeight: number, quality: number): Promise { return new Promise(async (resolve, reject) => { try { // Decode the base64 video string to an ArrayBuffer const videoBuffer = this.base64ToArrayBuffer(this.removeTextBeforeSlash(base64String,',')); - + // Create a Blob from the ArrayBuffer const videoBlob = new Blob([videoBuffer], { type: 'video/mp4' }); - + // Create an object URL from the Blob const videoObjectUrl = URL.createObjectURL(videoBlob); - + // Create a video element const video = document.createElement('video'); video.src = videoObjectUrl; - + // Wait for the video to load metadata video.addEventListener('loadedmetadata', async () => { const canvas = document.createElement('canvas'); let newWidth = video.videoWidth; let newHeight = video.videoHeight; - + if (newWidth > maxWidth) { newHeight *= maxWidth / newWidth; newWidth = maxWidth; } - + if (newHeight > maxHeight) { newWidth *= maxHeight / newHeight; newHeight = maxHeight; } - + canvas.width = newWidth; canvas.height = newHeight; - + const context = canvas.getContext('2d'); context?.drawImage(video, 0, 0, newWidth, newHeight); - + // Convert the canvas to a Blob with the correct MIME type canvas.toBlob(async (blob) => { if (blob) { // Read the Blob as an ArrayBuffer const compressedVideoBuffer = await this.readBlobAsArrayBuffer(blob); - + // Convert the ArrayBuffer back to base64 const compressedBase64 = this.arrayBufferToBase64(compressedVideoBuffer); - + resolve(compressedBase64); } else { reject('Error creating compressed video blob.'); } }, 'video/mp4', quality); - + }); - + } catch (error) { reject(error); } }); } */ - + /* async compressVideoBase64(base64String: string, maxWidth: number, maxHeight: number, quality: number): Promise { return new Promise(async (resolve, reject) => { @@ -718,62 +736,62 @@ export class NewPublicationPage implements OnInit { const trimmedBase64 = base64String.trim(); console.log(this.removeTextBeforeSlash(trimmedBase64,',')) const videoBuffer = this.base64ToArrayBuffer(this.removeTextBeforeSlash(trimmedBase64,',')); - + // Create a Blob from the ArrayBuffer const videoBlob = new Blob([videoBuffer], { type: 'video/mp4' }); - + // Create an object URL from the Blob const videoObjectUrl = URL.createObjectURL(videoBlob); - + // Create a video element const video = document.createElement('video'); video.src = videoObjectUrl; - + // Wait for the video to load metadata video.addEventListener('loadedmetadata', async () => { const canvas = document.createElement('canvas'); let newWidth = video.videoWidth; let newHeight = video.videoHeight; - + if (newWidth > maxWidth) { newHeight *= maxWidth / newWidth; newWidth = maxWidth; } - + if (newHeight > maxHeight) { newWidth *= maxHeight / newHeight; newHeight = maxHeight; } - + canvas.width = newWidth; canvas.height = newHeight; - + const context = canvas.getContext('2d'); context?.drawImage(video, 0, 0, newWidth, newHeight); - + // Convert the canvas to a Blob canvas.toBlob(async (blob) => { if (blob) { // Read the Blob as an ArrayBuffer const compressedVideoBuffer = await this.readBlobAsArrayBuffer(blob); - + // Convert the ArrayBuffer back to base64 const compressedBase64 = this.arrayBufferToBase64(compressedVideoBuffer); - + resolve(compressedBase64); } else { reject('Error creating compressed video blob.'); } }, 'video/mp4', quality); - + }); - + } catch (error) { reject(error); } }); } */ - + private base64ToArrayBuffer(base64: string): ArrayBuffer { const binaryString = window.atob(base64); const len = binaryString.length; @@ -783,7 +801,7 @@ export class NewPublicationPage implements OnInit { } return bytes.buffer; } - + private async readBlobAsArrayBuffer(blob: Blob): Promise { return new Promise((resolve, reject) => { const reader = new FileReader(); @@ -797,12 +815,12 @@ export class NewPublicationPage implements OnInit { reader.readAsArrayBuffer(blob); }); } - + private arrayBufferToBase64(buffer: ArrayBuffer): string { const binary = String.fromCharCode(...new Uint8Array(buffer)); return btoa(binary); } - + fileSizeToMB(sizeInBytes) { var sizeInMB = (sizeInBytes / (1024 * 1024)).toFixed(2); @@ -810,8 +828,199 @@ export class NewPublicationPage implements OnInit { return parseInt(sizeInMB) } - deleteFromSeletedContent(index){ - this.seletedContent.splice(index,1) + deleteFromSeletedContent(index) { + this.seletedContent.splice(index, 1) } } + +class UploadFileUseCase { + LakefsRepositoryService: LakefsRepositoryService = window["LakefsRepositoryService"] + constructor() {} + execute(attachment: PublicationAttachmentEntity) { + + const file: File = attachment.blob + + const chunkSize = 1024 * 100; // Adjust the chunk size as needed + const fileSize = file.size; + let uploadedSize = 0 + const totalChunks = Math.ceil(fileSize / chunkSize); + let offset = 0; + let i = 1; + let j = 0; + let path; + + function count () { + j++ + return j + } + + const readAndUploadChunk = async(index: number) => { + return new Promise((resolve, reject) => { + const chunk = file.slice(offset, offset + chunkSize); + const reader = new FileReader(); + + reader.onload = async () => { + const blob = new Blob([reader.result as ArrayBuffer]); + const formData = new FormData(); + const file = new File([blob], "test.mp4", { type: blob.type }); + + uploadedSize =+ file.size + + formData.append("blobFile", file); + formData.append("length", totalChunks.toString()); + formData.append("index", index.toString()); + formData.append("path", path); + + try { + const response = await this.LakefsRepositoryService.uploadFile(formData).toPromise() + + console.log({response}) + + resolve() + } catch (erro) { + reject() + } + + }; + + reader.readAsArrayBuffer(chunk); + offset += chunkSize; + }); + } + + const loop = async() => { + + for (let index = 2; index <= totalChunks; index++) { + await readAndUploadChunk(index); + } + + } + + const startUpload = async() => { + const index = count(); + const chunk = file.slice(offset, offset + chunkSize); + const reader = new FileReader(); + + reader.onload = async () => { + const blob = new Blob([reader.result as ArrayBuffer]); + const formData = new FormData(); + const file = new File([blob], "test.mp4", { type: blob.type }); + uploadedSize =+ file.size + formData.append("blobFile", file); + formData.append("length", totalChunks.toString()); + formData.append("index", index.toString()); + + + const response: any = await this.LakefsRepositoryService.uploadFile(formData).toPromise() + + console.log({ response, index }); + if (index === 1) { + path = response.path; + } + + await loop(); + }; + + reader.readAsArrayBuffer(chunk); + offset += chunkSize; + } + + startUpload(); + + + } +} + +class PublicationAttachmentEntity { + FileBase64: string + FileExtension: string + FileType: 'image' | 'video' + OriginalFileName: string + blob: any + + constructor({base64, extension, blob = null, OriginalFileName = null, FileType}) { + this.FileBase64 = base64; + this.FileExtension = extension; + this.blob = blob + this.OriginalFileName = OriginalFileName + this.FileType = FileType + + this.fixFileBase64(); + } + + fixFileBase64() { + if(this.FileType == 'image' ) { + if(!this.FileBase64.startsWith('data:')) { + this.FileBase64 = 'data:image/jpg;base64,' + this.FileBase64 + } + } else if (this.FileType == 'video' ) { + if(!this.FileBase64.startsWith('data:')) { + this.FileBase64 = 'data:video/mp4;base64,' + this.FileBase64 + } + + } + } +} + +interface IPublicationFormModelEntity { + DateIndex: any + DocumentId: any + ProcessId: any + Title: any + Message: any + DatePublication: any + Files: PublicationAttachmentEntity[] +} + +class PublicationFormModel implements IPublicationFormModelEntity { + constructor() {} + DateIndex: any; + DocumentId: any; + ProcessId: any; + Title: any; + Message: any; + DatePublication: any; + OriginalFileName: string; + Files: PublicationAttachmentEntity[]; + + setData(data: IPublicationFormModelEntity) { + Object.assign(this, data) + } +} + +class PublicationFormMV { + + private UploadFileUseCase = new UploadFileUseCase() + private form = new PublicationFormModel() + + setDataToFrom(data: IPublicationFormModelEntity) { + this.form.setData(data) + } + + private getVideoFiles() { + return this.form.Files.filter( x => x.FileType == 'video') + } + + private async upload(PublicationAttachmentEntity: PublicationAttachmentEntity) { + + console.log(PublicationAttachmentEntity) + this.UploadFileUseCase.execute(PublicationAttachmentEntity) + } + + uploadVideosFiles() { + + const videosFiles = this.getVideoFiles() + + console.log(this.form) + + for(const file of videosFiles) { + this.upload(file) + } + } + +} + + + + diff --git a/src/app/shared/publication/new-publication/usercase/upload-file-user-case.service.spec.ts b/src/app/shared/publication/new-publication/usercase/upload-file-user-case.service.spec.ts new file mode 100644 index 000000000..f1740a2e8 --- /dev/null +++ b/src/app/shared/publication/new-publication/usercase/upload-file-user-case.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { UploadFileUserCaseService } from './upload-file-user-case.service'; + +describe('UploadFileUserCaseService', () => { + let service: UploadFileUserCaseService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(UploadFileUserCaseService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/shared/publication/new-publication/usercase/upload-file-user-case.service.ts b/src/app/shared/publication/new-publication/usercase/upload-file-user-case.service.ts new file mode 100644 index 000000000..e52bbdc21 --- /dev/null +++ b/src/app/shared/publication/new-publication/usercase/upload-file-user-case.service.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@angular/core'; +import { LakefsRepositoryService } from "src/app/shared/repository/lakefs/lakefs-repository.service" +import { IPublicationFormModelEntity, IPublicationAttachmentEntity } from "src/app/shared/publication/new-publication/interface/interface" +@Injectable({ + providedIn: 'root' +}) +export class UploadFileUserCaseService { + + constructor(LakefsRepositoryService: LakefsRepositoryService) {} + execute(attachment: IPublicationAttachmentEntity) { + + const file: File = attachment.blob + + const chunkSize = 1024 * 1024; // Adjust the chunk size as needed + const fileSize = file.size; + const totalChunks = Math.ceil(fileSize / chunkSize); + let offset = 0; + let i = 1; + + + // while (offset < file.size) { + // console.log("while", i) + // const chunk = file.slice(offset, offset + chunkSize); + // const reader = new FileReader(); + + // reader.onload = async () => { + + // // const uint8Array = new Uint8Array(reader.result as ArrayBuffer) + // // Convert Uint8Array to Blob + // const blob = new Blob([reader.result as ArrayBuffer]); + + // const formData = new FormData(); + // formData.append("blob", blob) + // formData.append("length", totalChunks.toString()) + // formData.append("length", i.toString()) + + // this.LakefsRepositoryService.uploadFile(formData) + + // }; + // reader.readAsArrayBuffer(chunk); + // offset += chunkSize; + // i++; + // } + } +} diff --git a/src/app/shared/repository/lakefs/lakefs-repository.service.spec.ts b/src/app/shared/repository/lakefs/lakefs-repository.service.spec.ts new file mode 100644 index 000000000..ca0d56e5a --- /dev/null +++ b/src/app/shared/repository/lakefs/lakefs-repository.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { LakefsRepositoryService } from './lakefs-repository.service'; + +describe('LakefsRepositoryService', () => { + let service: LakefsRepositoryService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LakefsRepositoryService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/shared/repository/lakefs/lakefs-repository.service.ts b/src/app/shared/repository/lakefs/lakefs-repository.service.ts new file mode 100644 index 000000000..70a5ba4bd --- /dev/null +++ b/src/app/shared/repository/lakefs/lakefs-repository.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@angular/core'; +import { MiddlewareServiceService } from "src/app/shared/API/middleware/middleware-service.service"; + +@Injectable({ + providedIn: 'root' +}) +export class LakefsRepositoryService { + + constructor(public MiddlewareServiceService: MiddlewareServiceService) { + window["LakefsRepositoryService"] = this + } + + + uploadFile(formData: FormData) { + return this.MiddlewareServiceService.uploadFileLK(formData) + } +}