From 1604e1ca0bd9df358d64c90bdbaee5295cd47306 Mon Sep 17 00:00:00 2001 From: Saiprabhu007 Date: Thu, 20 Jun 2024 17:26:11 +0530 Subject: [PATCH] fix: ensure an error msg is displayed when max-no of files is 0 and restrict user to upload file --- .../Filepicker/FilePicker_Max_No_Spec.js | 35 +++++++++++++++++ .../FilePickerWidgetV2/component/index.tsx | 39 ++++++++++++------- .../widgets/FilePickerWidgetV2/constants.ts | 2 + .../FilePickerWidgetV2/widget/index.tsx | 27 +++++++++---- 4 files changed, 82 insertions(+), 21 deletions(-) create mode 100644 app/client/cypress/e2e/Regression/ClientSide/Widgets/Filepicker/FilePicker_Max_No_Spec.js diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Filepicker/FilePicker_Max_No_Spec.js b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Filepicker/FilePicker_Max_No_Spec.js new file mode 100644 index 000000000000..7c721d40f3d8 --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Filepicker/FilePicker_Max_No_Spec.js @@ -0,0 +1,35 @@ +import { + agHelper, + draggableWidgets, + entityExplorer, + propPane, + } from "../../../../../support/Objects/ObjectsCore"; + import EditorNavigation, { + EntityType, + } from "../../../../../support/Pages/EditorNavigation"; + const commonlocators = require("../../../../../locators/commonlocators.json"); + + describe( + "FilePicker Widget Functionality", + { tags: ["@tag.Widget", "@tag.Filepicker"] }, + function () { + before(() => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.FILEPICKER); + }); + + it("Should display an error message when clicked on filepicker when max no-of files are set to 0", () => { + EditorNavigation.SelectEntityByName("FilePicker1", EntityType.Widget); + propPane.UpdatePropertyFieldValue("Max no. of files", "1"); + const fixturePath = "cypress/fixtures/dummy.pdf"; + cy.get(commonlocators.filepickerv2).click(); + cy.get(commonlocators.filePickerInput).first().selectFile(fixturePath, { + force: true, + }); + cy.get(commonlocators.filePickerUploadButton).click(); + cy.get(commonlocators.dashboardItemName).contains("dummy.pdf"); + agHelper.GetNClick(commonlocators.filePickerRemoveButton, 0, true); + propPane.UpdatePropertyFieldValue("Max no. of files", "0"); + cy.get(commonlocators.filepickerv2).click(); + }); + }, + ); diff --git a/app/client/src/widgets/FilePickerWidgetV2/component/index.tsx b/app/client/src/widgets/FilePickerWidgetV2/component/index.tsx index f8d37b231a00..7e0fdfa1d01f 100644 --- a/app/client/src/widgets/FilePickerWidgetV2/component/index.tsx +++ b/app/client/src/widgets/FilePickerWidgetV2/component/index.tsx @@ -2,6 +2,12 @@ import React from "react"; import type { ComponentProps } from "widgets/BaseComponent"; import { BaseButton } from "widgets/ButtonWidget/component"; import { Colors } from "constants/Colors"; +import { theme } from "constants/DefaultTheme"; +import styled from "styled-components"; + +const ErrorMessage = styled.div` + color: ${theme.colors.error}; +`; function FilePickerComponent(props: FilePickerComponentProps) { let computedLabel = props.label; @@ -11,19 +17,22 @@ function FilePickerComponent(props: FilePickerComponentProps) { } return ( - + <> + + {props.errorMessage && {props.errorMessage}} + ); } export interface FilePickerComponentProps extends ComponentProps { @@ -38,10 +47,12 @@ export interface FilePickerComponentProps extends ComponentProps { maxWidth?: number; minWidth?: number; minHeight?: number; + maxNumFiles?: number; + errorMessage?: string | null; } FilePickerComponent.defaultProps = { backgroundColor: Colors.GREEN, }; -export default FilePickerComponent; +export default FilePickerComponent; \ No newline at end of file diff --git a/app/client/src/widgets/FilePickerWidgetV2/constants.ts b/app/client/src/widgets/FilePickerWidgetV2/constants.ts index 66022662dbfb..a92738c53bae 100644 --- a/app/client/src/widgets/FilePickerWidgetV2/constants.ts +++ b/app/client/src/widgets/FilePickerWidgetV2/constants.ts @@ -1,3 +1,5 @@ import { FileDataTypes } from "WidgetProvider/constants"; export default FileDataTypes; + +export const ERROR_MESSAGE="Cannot upload any files" \ No newline at end of file diff --git a/app/client/src/widgets/FilePickerWidgetV2/widget/index.tsx b/app/client/src/widgets/FilePickerWidgetV2/widget/index.tsx index 81c7174b072b..88cb169b9ce5 100644 --- a/app/client/src/widgets/FilePickerWidgetV2/widget/index.tsx +++ b/app/client/src/widgets/FilePickerWidgetV2/widget/index.tsx @@ -18,7 +18,7 @@ import { importUppy, isUppyLoaded } from "utils/importUppy"; import type { WidgetProps, WidgetState } from "widgets/BaseWidget"; import BaseWidget from "widgets/BaseWidget"; import FilePickerComponent from "../component"; -import FileDataTypes from "../constants"; +import FileDataTypes, { ERROR_MESSAGE } from "../constants"; import { DefaultAutocompleteDefinitions } from "widgets/WidgetUtils"; import type { AnvilConfig, @@ -49,6 +49,7 @@ class FilePickerWidget extends BaseWidget< areFilesLoading: false, isWaitingForUppyToLoad: false, isUppyModalOpen: false, + errorMessage: null, }; } @@ -318,7 +319,7 @@ class FilePickerWidget extends BaseWidget< { propertyName: "isVisible", label: "Visible", - helpText: "Controls the visibility of the widget", + helpText: "Controls visibility of the widget ", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, @@ -328,7 +329,7 @@ class FilePickerWidget extends BaseWidget< { propertyName: "isDisabled", label: "Disable", - helpText: "Disables input to this widget", + helpText: "Disables input for this widget", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, @@ -339,7 +340,7 @@ class FilePickerWidget extends BaseWidget< propertyName: "animateLoading", label: "Animate loading", controlType: "SWITCH", - helpText: "Controls the loading of the widget", + helpText: "Controls the widget's loading state", defaultValue: true, isJSConvertible: true, isBindProperty: true, @@ -374,7 +375,7 @@ class FilePickerWidget extends BaseWidget< children: [ { propertyName: "buttonColor", - helpText: "Changes the color of the button", + helpText: "Changes color of the button", label: "Button color", controlType: "COLOR_PICKER", isJSConvertible: true, @@ -391,7 +392,7 @@ class FilePickerWidget extends BaseWidget< propertyName: "borderRadius", label: "Border radius", helpText: - "Rounds the corners of the icon button's outer border edge", + "Rounds the corners of the icon button's outer border", controlType: "BORDER_RADIUS_OPTIONS", isJSConvertible: true, @@ -708,6 +709,11 @@ class FilePickerWidget extends BaseWidget< await this.reinitializeUppy(this.props); } this.clearFilesFromMemory(prevProps.selectedFiles); + const prevMaxNumFiles = prevProps.maxNumFiles ?? 0; + const currentMaxNumFiles = this.props.maxNumFiles ?? 0; + if (prevMaxNumFiles === 0 && currentMaxNumFiles > 0) { + this.setState({ errorMessage: null }); + } } // Reclaim the memory used by blobs. @@ -794,6 +800,11 @@ class FilePickerWidget extends BaseWidget< minHeight={this.props.minHeight} minWidth={this.props.minWidth} openModal={async () => { + if (this.props.maxNumFiles === 0) { + this.setState({ errorMessage: ERROR_MESSAGE }); + return; + } + this.setState({ errorMessage: null }); // If Uppy is still loading, show a spinner to indicate that handling the click // will take some time. // @@ -813,6 +824,7 @@ class FilePickerWidget extends BaseWidget< }} shouldFitContent={this.isAutoLayoutMode} widgetId={this.props.widgetId} + errorMessage={this.state.errorMessage} /> {this.state.isUppyModalOpen && ( @@ -827,6 +839,7 @@ interface FilePickerWidgetState extends WidgetState { areFilesLoading: boolean; isWaitingForUppyToLoad: boolean; isUppyModalOpen: boolean; + errorMessage: string | null; } interface FilePickerWidgetProps extends WidgetProps { @@ -847,4 +860,4 @@ interface FilePickerWidgetProps extends WidgetProps { export type FilePickerWidgetV2Props = FilePickerWidgetProps; export type FilePickerWidgetV2State = FilePickerWidgetState; -export default FilePickerWidget; +export default FilePickerWidget; \ No newline at end of file