From 7452a6a96a1f32be1382f3ae5a1c4314b07455f5 Mon Sep 17 00:00:00 2001 From: matheus-relief Date: Tue, 9 Jan 2024 15:14:44 -0300 Subject: [PATCH 1/2] fix: file upload inside dynamic panel --- .../form-modal/form-modal.component.ts | 3 +- .../src/lib/components/form/form.component.ts | 7 +- .../form-builder/form-builder.service.ts | 31 ++++++- .../form-helper/form-helper.service.ts | 86 +++++++++++-------- 4 files changed, 86 insertions(+), 41 deletions(-) diff --git a/libs/shared/src/lib/components/form-modal/form-modal.component.ts b/libs/shared/src/lib/components/form-modal/form-modal.component.ts index 0d33bf1bfb..44026b5650 100644 --- a/libs/shared/src/lib/components/form-modal/form-modal.component.ts +++ b/libs/shared/src/lib/components/form-modal/form-modal.component.ts @@ -40,6 +40,7 @@ import { SpinnerModule } from '@oort-front/ui'; import { UnsubscribeComponent } from '../utils/unsubscribe/unsubscribe.component'; import { FormHelpersService, + TemporaryFilesStorage, transformSurveyData, } from '../../services/form-helper/form-helper.service'; import { DialogModule } from '@oort-front/ui'; @@ -97,7 +98,7 @@ export class FormModalComponent private storedMergedData: any; public survey!: SurveyModel; - protected temporaryFilesStorage: any = {}; + protected temporaryFilesStorage: TemporaryFilesStorage = {}; @ViewChild('formContainer') formContainer!: ElementRef; diff --git a/libs/shared/src/lib/components/form/form.component.ts b/libs/shared/src/lib/components/form/form.component.ts index a58c4b590a..3eb57d947c 100644 --- a/libs/shared/src/lib/components/form/form.component.ts +++ b/libs/shared/src/lib/components/form/form.component.ts @@ -25,7 +25,10 @@ import { FormBuilderService } from '../../services/form-builder/form-builder.ser import { RecordHistoryComponent } from '../record-history/record-history.component'; import { TranslateService } from '@ngx-translate/core'; import { UnsubscribeComponent } from '../utils/unsubscribe/unsubscribe.component'; -import { FormHelpersService } from '../../services/form-helper/form-helper.service'; +import { + FormHelpersService, + TemporaryFilesStorage, +} from '../../services/form-helper/form-helper.service'; import { SnackbarService, UILayoutService } from '@oort-front/ui'; import { cloneDeep } from 'lodash'; @@ -55,7 +58,7 @@ export class FormComponent /** Indicates whether the search is active */ public surveyActive = true; /** Temporary storage for files */ - public temporaryFilesStorage: Record> = {}; + public temporaryFilesStorage: TemporaryFilesStorage = {}; /** Reference to the form container element */ @ViewChild('formContainer') formContainer!: ElementRef; /** Date when the form was last modified */ diff --git a/libs/shared/src/lib/services/form-builder/form-builder.service.ts b/libs/shared/src/lib/services/form-builder/form-builder.service.ts index 1648d81122..28a092a471 100644 --- a/libs/shared/src/lib/services/form-builder/form-builder.service.ts +++ b/libs/shared/src/lib/services/form-builder/form-builder.service.ts @@ -16,6 +16,7 @@ import { BehaviorSubject } from 'rxjs'; import { SnackbarService } from '@oort-front/ui'; import { FormHelpersService, + TemporaryFilesStorage, transformSurveyData, } from '../form-helper/form-helper.service'; import { difference } from 'lodash'; @@ -258,7 +259,7 @@ export class FormBuilderService { public addEventsCallBacksToSurvey( survey: SurveyModel, selectedPageIndex: BehaviorSubject, - temporaryFilesStorage: Record> + temporaryFilesStorage: TemporaryFilesStorage ) { survey.onAfterRenderSurvey.add(() => { // Open survey on a specific page (openOnQuestionValuesPage has priority over openOnPage) @@ -315,11 +316,33 @@ export class FormBuilderService { * @param temporaryFilesStorage Temporary files saved while executing the survey * @param options Options regarding the upload */ - private onUploadFiles(temporaryFilesStorage: any, options: any): void { + private onUploadFiles( + temporaryFilesStorage: TemporaryFilesStorage, + options: any + ): void { if (temporaryFilesStorage[options.name] !== undefined) { - temporaryFilesStorage[options.name].concat(options.files); + // Find if there is files for the same question + const cachedQuestion = temporaryFilesStorage[options.name].find( + (c) => c.question === options.question + ); + + // If there is, add the file to the existing array + if (cachedQuestion) { + cachedQuestion.files.concat(options.files); + } else { + // If not, create a new entry + temporaryFilesStorage[options.name].push({ + files: options.files, + question: options.question, + }); + } } else { - temporaryFilesStorage[options.name] = options.files; + temporaryFilesStorage[options.name] = [ + { + files: options.files, + question: options.question, + }, + ]; } let content: any[] = []; options.files.forEach((file: any) => { diff --git a/libs/shared/src/lib/services/form-helper/form-helper.service.ts b/libs/shared/src/lib/services/form-helper/form-helper.service.ts index e3781aea7e..2afc733163 100644 --- a/libs/shared/src/lib/services/form-helper/form-helper.service.ts +++ b/libs/shared/src/lib/services/form-helper/form-helper.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { IPanel, PageModel, + QuestionFileModel, QuestionPanelDynamicModel, SurveyModel, } from 'survey-core'; @@ -22,6 +23,15 @@ import { WorkflowService } from '../workflow/workflow.service'; import { ApplicationService } from '../application/application.service'; import { DomService } from '../dom/dom.service'; +/** Type definition for the temporary file storage object */ +export type TemporaryFilesStorage = Record< + string, + { + question: QuestionFileModel; + files: File[]; + }[] +>; + /** * Applies custom logic to survey data values. * @@ -157,49 +167,59 @@ export class FormHelpersService { */ async uploadFiles( survey: SurveyModel, - temporaryFilesStorage: any, + temporaryFilesStorage: TemporaryFilesStorage, formId: string | undefined ): Promise { if (!formId) { throw new Error('Form id is not defined'); } - - const data = survey.data; const questionsToUpload = Object.keys(temporaryFilesStorage); for (const name of questionsToUpload) { - const files = temporaryFilesStorage[name]; - for (const [index, file] of files.entries()) { - const path = await this.downloadService.uploadBlob( - file, - BlobType.RECORD_FILE, - formId - ); - if (path) { - const fileContent = data[name][index].content; - data[name][index].content = path; - - // Check if any other question is using the same file - survey.getAllQuestions().forEach((question) => { - const questionType = question.getType(); - if ( - questionType !== 'file' || - // Only change files that are not in the temporary storage - // meaning their values came from the default values - !!temporaryFilesStorage[question.name] - ) - return; - - const files = data[question.name] ?? []; - files.forEach((file: any) => { - if (file && file.content === fileContent) { - file.content = path; + const cachedQuestions = temporaryFilesStorage[name]; + + if (!cachedQuestions) { + return; + } + + for (const { files, question } of cachedQuestions) { + for (const [index, file] of files.entries()) { + const path = await this.downloadService.uploadBlob( + file, + BlobType.RECORD_FILE, + formId + ); + if (path) { + const fileContent = question.value?.[index]?.content; + const value = cloneDeep(question.value); + + if (question.value?.[index]?.content) { + value[index] = { ...value[index], content: path }; + question.value = value; + } + + // Check if any other question is using the same file + survey.getAllQuestions().forEach((question) => { + const questionType = question.getType(); + if ( + questionType !== 'file' || + // Only change files that are not in the temporary storage + // meaning their values came from the default values + !!temporaryFilesStorage[question.name] + ) { + return; } + + const files = survey.data[question.name] ?? []; + files.forEach((file: any) => { + if (file && file.content === fileContent) { + file.content = path; + } + }); }); - }); + } } } } - survey.data = cloneDeep(data); } /** @@ -496,9 +516,7 @@ export class FormHelpersService { * * @param storage Storage to clear */ - public clearTemporaryFilesStorage( - storage: Record> - ): void { + public clearTemporaryFilesStorage(storage: TemporaryFilesStorage): void { Object.keys(storage).forEach((key) => { delete storage[key]; }); From 33d16894b678fc182f5d54b1965c43fbdd33b5d7 Mon Sep 17 00:00:00 2001 From: matheus-relief Date: Tue, 9 Jan 2024 15:17:37 -0300 Subject: [PATCH 2/2] typo --- .../src/lib/services/form-builder/form-builder.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/shared/src/lib/services/form-builder/form-builder.service.ts b/libs/shared/src/lib/services/form-builder/form-builder.service.ts index 28a092a471..b1658c292e 100644 --- a/libs/shared/src/lib/services/form-builder/form-builder.service.ts +++ b/libs/shared/src/lib/services/form-builder/form-builder.service.ts @@ -321,12 +321,12 @@ export class FormBuilderService { options: any ): void { if (temporaryFilesStorage[options.name] !== undefined) { - // Find if there is files for the same question + // Find if there are files for the same question const cachedQuestion = temporaryFilesStorage[options.name].find( (c) => c.question === options.question ); - // If there is, add the file to the existing array + // If there are, add the file to the existing array if (cachedQuestion) { cachedQuestion.files.concat(options.files); } else {