Skip to content

Commit

Permalink
Resolved #7314 - File Upload - Allow uploading valid files and displa…
Browse files Browse the repository at this point in the history
…y an error message in case of invalid files at the same time (#7326)

* Resolved #7314 - File Upload - Allow uploading valid files and display an error message in case of invalid files at the same time

* Work for #7314 - File Upload - Allow uploading valid files and display an error message in case of invalid files at the same time - fixed f-test

* Work for#7314 - File Upload - Allow uploading valid files and display an error message in case of invalid files at the same time - Changed API

* Update options.callback description

* Fixed #7314 - File Upload - Allow uploading valid files and display an error message in case of invalid files at the same time - Updated error message text

---------

Co-authored-by: tsv2013 <tsv2013@noreply.github.com>
Co-authored-by: RomanTsukanov <sergeich16@gmail.com>
  • Loading branch information
3 people committed Nov 23, 2023
1 parent fa998b9 commit 5b608d0
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 97 deletions.
3 changes: 2 additions & 1 deletion src/base-interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ export interface ISurvey extends ITextProcessor, ISurveyErrorOwner {
question: IQuestion,
name: string,
files: File[],
uploadingCallback: (status: string, data: any) => any
// uploadingCallback: (status: string | Array<any>, data: any) => any
uploadingCallback: (data: any | Array<any>, errors?: any | Array<any>) => any
): any;
downloadFile(
question: IQuestion,
Expand Down
1 change: 1 addition & 0 deletions src/localization/english.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export var englishStrings = {
urlGetChoicesError:
"The request returned empty data or the 'path' property is incorrect",
exceedMaxSize: "The file size should not exceed {0}.",
noUploadFilesHandler: "Files cannot be uploaded. Please add a handler for the 'onUploadFiles' event.",
otherRequiredError: "Response required: enter another value.",
uploadingFile:
"Your file is uploading. Please wait several seconds and try again.",
Expand Down
34 changes: 27 additions & 7 deletions src/question_file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,15 +625,25 @@ export class QuestionFileModel extends Question {
});
} else {
if (this.survey) {
this.survey.uploadFiles(this, this.name, files, (status, data) => {
if (status === "error") {
this.errors.push(new UploadingFileError(data, this));
this.stateChanged("error");
this.stateChanged("loaded");
this.survey.uploadFiles(this, this.name, files, (arg1: any, arg2: any) => {
if (Array.isArray(arg1)) {
this.value = (this.value || []).concat(
arg1.map((r: any) => {
return {
name: r.file.name,
type: r.file.type,
content: r.content,
};
})
);
if (Array.isArray(arg2)) {
arg2.forEach(error => this.errors.push(new UploadingFileError(error, this)));
this.stateChanged("error");
}
}
if (status === "success") {
if (arg1 === "success" && Array.isArray(arg2)) {
this.value = (this.value || []).concat(
data.map((r: any) => {
arg2.map((r: any) => {
return {
name: r.file.name,
type: r.file.type,
Expand All @@ -642,6 +652,16 @@ export class QuestionFileModel extends Question {
})
);
}
if (arg1 === "error") {
if (typeof (arg2) === "string") {
this.errors.push(new UploadingFileError(arg2, this));
}
if (Array.isArray(arg2) && arg2.length > 0) {
arg2.forEach(error => this.errors.push(new UploadingFileError(error, this)));
}
this.stateChanged("error");
}
this.stateChanged("loaded");
});
}
}
Expand Down
22 changes: 11 additions & 11 deletions src/survey-events-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ export interface MatrixDropdownQuestionEventMixin {
question: QuestionMatrixDropdownModelBase;
}
export interface MatrixDynamicQuestionEventMixin {
/**
* A Dynamic Matrix question instance for which the event is raised.
*/
/**
* A Dynamic Matrix question instance for which the event is raised.
*/
question: QuestionMatrixDynamicModel;
}
export interface PanelEventMixin {
Expand Down Expand Up @@ -284,11 +284,11 @@ export interface ElementRemovedEvent {
*/
name: string;
}
export interface QuestionAddedEvent extends QuestionEventMixin, ElementAddedEvent {}
export interface QuestionRemovedEvent extends QuestionEventMixin, ElementRemovedEvent {}
export interface PanelAddedEvent extends PanelEventMixin, ElementAddedEvent {}
export interface PanelRemovedEvent extends PanelEventMixin, ElementRemovedEvent {}
export interface PageAddedEvent extends PageEventMixin {}
export interface QuestionAddedEvent extends QuestionEventMixin, ElementAddedEvent { }
export interface QuestionRemovedEvent extends QuestionEventMixin, ElementRemovedEvent { }
export interface PanelAddedEvent extends PanelEventMixin, ElementAddedEvent { }
export interface PanelRemovedEvent extends PanelEventMixin, ElementRemovedEvent { }
export interface PageAddedEvent extends PageEventMixin { }
export interface ValidateQuestionEvent extends QuestionEventMixin {
/**
* An error message that you should specify if validation fails.
Expand Down Expand Up @@ -495,9 +495,9 @@ export interface LoadFilesEvent extends FileQuestionEventMixin {
}
export interface UploadFilesEvent extends LoadFilesEvent {
/**
* A callback function that you should call when a file is uploaded successfully or when file upload fails. Pass `"success"` or `"error"` as the first argument to indicate the operation status. As the second argument, you can pass the uploaded file's data if file upload was successful or an error message if file upload failed.
* A callback function that you should call when a file is uploaded successfully or when file upload fails. Pass an array of successfully uploaded files as the first argument. As the second argument, you can pass an array of error messages if file upload failed.
*/
callback: (status: string, data?: any) => any;
callback: (data: any | Array<any>, errors?: any | Array<any>) => any;
/**
* An array of JavaScript <a href="https://developer.mozilla.org/en-US/docs/Web/API/File" target="_blank">File</a> objects that represent files to upload.
*/
Expand Down Expand Up @@ -756,7 +756,7 @@ export interface MatrixCellValueBaseEvent extends MatrixDropdownQuestionEventMix

}

export interface MatrixCellValueChangedEvent extends MatrixCellValueBaseEvent {}
export interface MatrixCellValueChangedEvent extends MatrixCellValueBaseEvent { }
export interface MatrixCellValueChangingEvent extends MatrixCellValueBaseEvent {
/**
* A previous cell value.
Expand Down
8 changes: 4 additions & 4 deletions src/survey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5019,18 +5019,18 @@ export class SurveyModel extends SurveyElementCore
* @param question A [File Upload question instance](https://surveyjs.io/form-library/documentation/api-reference/file-model).
* @param name The File Upload question's [`name`](https://surveyjs.io/form-library/documentation/api-reference/file-model#name).
* @param files An array of JavaScript <a href="https://developer.mozilla.org/en-US/docs/Web/API/File" target="_blank">File</a> objects that represent files to upload.
* @param callback A callback function that allows you to get the upload status (`"success"` or `"error"`) and file data.
* @param callback A callback function that allows you to access successfully uploaded files as the first argument. If any files fail to upload, the second argument contains an array of error messages.
* @see onUploadFiles
* @see downloadFile
*/
public uploadFiles(
question: QuestionFileModel,
name: string,
files: File[],
callback: (status: string, data: any) => any
callback: (data: any | Array<any>, errors?: any | Array<any>) => any
) {
if (this.onUploadFiles.isEmpty) {
callback("error", files);
callback("error", this.getLocString("noUploadFilesHandler"));
} else {
this.onUploadFiles.fire(this, {
question: question,
Expand Down Expand Up @@ -5130,7 +5130,7 @@ export class SurveyModel extends SurveyElementCore
protected uploadFilesCore(
name: string,
files: File[],
uploadingCallback: (status: string, data: any) => any
uploadingCallback: (data: any | Array<any>, errors?: any | Array<any>,) => any
) {
var responses: Array<any> = [];
files.forEach((file) => {
Expand Down

0 comments on commit 5b608d0

Please sign in to comment.