Skip to content

chore: External contri/fix/bug 130 file picker widget able to pick a file when max no of files is defined as zero 0 14857 #34893

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: release
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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();
});
Comment on lines +20 to +33
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test case is valid but consider adding assertions to verify the error message.

The test case is valid for verifying the error message when the max number of files is set to 0. However, consider adding assertions to explicitly verify the presence of the error message.

+ cy.get(commonlocators.filePickerErrorMessage)
+   .should("exist")
+   .and("contain.text", "Cannot upload any files");
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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();
});
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();
cy.get(commonlocators.filePickerErrorMessage)
.should("exist")
.and("contain.text", "Cannot upload any files");
});

},
);
39 changes: 25 additions & 14 deletions app/client/src/widgets/FilePickerWidgetV2/component/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -11,19 +17,22 @@ function FilePickerComponent(props: FilePickerComponentProps) {
}

return (
<BaseButton
borderRadius={props.borderRadius}
boxShadow={props.boxShadow}
buttonColor={props.buttonColor}
disabled={props.isDisabled}
loading={props.isLoading}
maxWidth={props.maxWidth}
minHeight={props.minHeight}
minWidth={props.minWidth}
onClick={props.openModal}
shouldFitContent={props.shouldFitContent}
text={computedLabel}
/>
<>
<BaseButton
borderRadius={props.borderRadius}
boxShadow={props.boxShadow}
buttonColor={props.buttonColor}
disabled={props.isDisabled}
loading={props.isLoading}
maxWidth={props.maxWidth}
minHeight={props.minHeight}
minWidth={props.minWidth}
onClick={props.openModal}
shouldFitContent={props.shouldFitContent}
text={computedLabel}
/>
{props.errorMessage && <ErrorMessage>{props.errorMessage}</ErrorMessage>}
</>
);
}
export interface FilePickerComponentProps extends ComponentProps {
Expand All @@ -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;
2 changes: 2 additions & 0 deletions app/client/src/widgets/FilePickerWidgetV2/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { FileDataTypes } from "WidgetProvider/constants";

export default FileDataTypes;

export const ERROR_MESSAGE="Cannot upload any files"
27 changes: 20 additions & 7 deletions app/client/src/widgets/FilePickerWidgetV2/widget/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -49,6 +49,7 @@ class FilePickerWidget extends BaseWidget<
areFilesLoading: false,
isWaitingForUppyToLoad: false,
isUppyModalOpen: false,
errorMessage: null,
};
}

Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
//
Expand All @@ -813,6 +824,7 @@ class FilePickerWidget extends BaseWidget<
}}
shouldFitContent={this.isAutoLayoutMode}
widgetId={this.props.widgetId}
errorMessage={this.state.errorMessage}
/>

{this.state.isUppyModalOpen && (
Expand All @@ -827,6 +839,7 @@ interface FilePickerWidgetState extends WidgetState {
areFilesLoading: boolean;
isWaitingForUppyToLoad: boolean;
isUppyModalOpen: boolean;
errorMessage: string | null;
}

interface FilePickerWidgetProps extends WidgetProps {
Expand All @@ -847,4 +860,4 @@ interface FilePickerWidgetProps extends WidgetProps {
export type FilePickerWidgetV2Props = FilePickerWidgetProps;
export type FilePickerWidgetV2State = FilePickerWidgetState;

export default FilePickerWidget;
export default FilePickerWidget;
Loading