From 4b80ea27e9bf662d56bd3f4e9a2bc491dd99856a Mon Sep 17 00:00:00 2001 From: Paul Li <82799722+wmdev0808@users.noreply.github.com> Date: Thu, 24 Feb 2022 11:37:54 +0800 Subject: [PATCH] fix: Some .jpg images don't load in the Image Widget (#11247) --- .../DisplayWidgets/Image_spec.js | 16 ++++++++++++ app/client/src/ce/constants/messages.ts | 2 ++ .../widgets/ImageWidget/component/index.tsx | 26 +++++++++++++++---- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Image_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Image_spec.js index 7257026a17..f3d2afe846 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Image_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/DisplayWidgets/Image_spec.js @@ -65,6 +65,22 @@ describe("Image Widget Functionality", function() { cy.PublishtheApp(); cy.get(publish.imageWidget).should("be.visible"); }); + + it("In case of an image loading error, show off the error message", () => { + cy.get(publish.backToEditor).click(); + cy.openPropertyPane("imagewidget"); + // Invalid image url + const invalidImageUrl = "https://www.example.com/does-not-exist.jpg"; + cy.testCodeMirror(invalidImageUrl); + + // Show off error message + cy.get( + `${viewWidgetsPage.imageWidget} div[data-testid=styledImage]`, + ).should("not.exist"); + cy.get( + `${viewWidgetsPage.imageWidget} [data-testid="error-container"]`, + ).contains("Unable to display the image"); + }); }); afterEach(() => { // put your clean up code if any diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index 7d428af0c5..83570b4b15 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -1031,3 +1031,5 @@ export const CONTEXT_MOVE = () => "Move to page"; export const CONTEXT_COPY = () => "Copy to page"; export const CONTEXT_DELETE = () => "Delete"; export const CONTEXT_NO_PAGE = () => "No pages"; + +export const IMAGE_LOAD_ERROR = () => "Unable to display the image"; diff --git a/app/client/src/widgets/ImageWidget/component/index.tsx b/app/client/src/widgets/ImageWidget/component/index.tsx index 88e883bbbd..5b9c53235a 100644 --- a/app/client/src/widgets/ImageWidget/component/index.tsx +++ b/app/client/src/widgets/ImageWidget/component/index.tsx @@ -3,6 +3,7 @@ import { ComponentProps } from "widgets/BaseComponent"; import styled from "styled-components"; import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch"; import { Colors } from "constants/Colors"; +import { createMessage, IMAGE_LOAD_ERROR } from "ce/constants/messages"; export interface StyledImageProps { defaultImageUrl: string; @@ -26,8 +27,8 @@ export const StyledImage = styled.div< cursor: ${(props) => props.showHoverPointer && props.onClick ? "pointer" : "inherit"}; background: ${(props) => props.backgroundColor}; - background-image: ${(props) => - `url(${props.imageError ? props.defaultImageUrl : props.imageUrl})`}; + ${({ defaultImageUrl, imageError, imageUrl }) => + !imageError && `background-image: url("${imageUrl || defaultImageUrl}")`}; background-position: center; background-repeat: no-repeat; height: 100%; @@ -84,6 +85,12 @@ const ControlBtn = styled.div` } `; +const ErrorContainer = styled.div` + display: flex; + align-items: center; + justify-content: center; +`; + enum ZoomingState { MAX_ZOOMED_OUT = "MAX_ZOOMED_OUT", MAX_ZOOMED_IN = "MAX_ZOOMED_IN", @@ -108,9 +115,10 @@ class ImageComponent extends React.Component< zoomingState: ZoomingState.MAX_ZOOMED_OUT, }; } + render() { - const { maxZoomLevel } = this.props; - const { imageRotation } = this.state; + const { imageUrl, maxZoomLevel } = this.props; + const { imageError, imageRotation } = this.state; const zoomActive = maxZoomLevel !== undefined && maxZoomLevel > 1 && !this.isPanning; const isZoomingIn = this.state.zoomingState === ZoomingState.MAX_ZOOMED_OUT; @@ -119,6 +127,14 @@ class ImageComponent extends React.Component< cursor = isZoomingIn ? "zoom-in" : "zoom-out"; } if (this.props.onClick) cursor = "pointer"; + + if (imageUrl && imageError) + return ( + + {createMessage(IMAGE_LOAD_ERROR)} + + ); + return (