feat: Add deprecation warning badge to deprecated widgets (#13381)

This Change also introduces, isDeprecated flag to widget config, when true will add the warning to the widget's propertyPane.
This commit is contained in:
rahulramesha 2022-05-25 15:08:32 +05:30 committed by GitHub
parent 30ddc92e67
commit a2688bb4da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 458 additions and 22 deletions

View File

@ -0,0 +1,288 @@
{
"dsl": {
"widgetName": "MainContainer",
"backgroundColor": "none",
"rightColumn": 1224,
"snapColumns": 64,
"detachFromLayout": true,
"widgetId": "0",
"topRow": 0,
"bottomRow": 1140,
"containerStyle": "none",
"snapRows": 111,
"parentRowSpace": 1,
"type": "CANVAS_WIDGET",
"canExtend": true,
"version": 57,
"minHeight": 1120,
"parentColumnSpace": 1,
"dynamicBindingPathList": [],
"leftColumn": 0,
"children": [
{
"widgetName": "Input1",
"displayName": "Input",
"iconSVG": "/static/media/icon.9f505595.svg",
"topRow": 1,
"bottomRow": 5,
"parentRowSpace": 10,
"labelWidth": 5,
"autoFocus": false,
"type": "INPUT_WIDGET",
"hideCard": false,
"animateLoading": true,
"parentColumnSpace": 30.0625,
"resetOnSubmit": true,
"leftColumn": 1,
"labelPosition": "Left",
"labelStyle": "",
"inputType": "TEXT",
"isDisabled": false,
"key": "275yj6r1or",
"isRequired": false,
"isDeprecated": true,
"rightColumn": 21,
"widgetId": "vt14lljb7u",
"isVisible": true,
"label": "",
"allowCurrencyChange": false,
"version": 1,
"parentId": "0",
"labelAlignment": "left",
"renderMode": "CANVAS",
"isLoading": false,
"iconAlign": "left",
"defaultText": ""
},
{
"widgetName": "Select1",
"isFilterable": false,
"displayName": "Select",
"iconSVG": "/static/media/icon.bd99caba.svg",
"labelText": "Label",
"topRow": 6,
"bottomRow": 13,
"parentRowSpace": 10,
"labelWidth": 5,
"type": "DROP_DOWN_WIDGET",
"serverSideFiltering": false,
"hideCard": false,
"defaultOptionValue": "GREEN",
"selectionType": "SINGLE_SELECT",
"animateLoading": true,
"parentColumnSpace": 30.0625,
"leftColumn": 1,
"labelPosition": "Left",
"options": [
{
"label": "Blue",
"value": "BLUE"
},
{
"label": "Green",
"value": "GREEN"
},
{
"label": "Red",
"value": "RED"
}
],
"placeholderText": "Select option",
"isDisabled": false,
"key": "s12wyz7ve1",
"isRequired": false,
"isDeprecated": true,
"rightColumn": 21,
"widgetId": "7abukaxyhu",
"isVisible": true,
"version": 1,
"parentId": "0",
"labelAlignment": "left",
"renderMode": "CANVAS",
"isLoading": false
},
{
"widgetName": "DatePicker1",
"dateFormat": "YYYY-MM-DD HH:mm",
"displayName": "DatePicker",
"iconSVG": "/static/media/icon.300e5ab8.svg",
"topRow": 15,
"bottomRow": 19,
"parentRowSpace": 10,
"type": "DATE_PICKER_WIDGET",
"hideCard": false,
"animateLoading": true,
"parentColumnSpace": 30.0625,
"leftColumn": 1,
"isDisabled": false,
"key": "ovo8lmv8tj",
"defaultDate": "2022-04-27 19:58",
"isDeprecated": true,
"rightColumn": 21,
"widgetId": "4szxg4jmpp",
"isVisible": true,
"datePickerType": "DATE_PICKER",
"label": "",
"version": 1,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false
},
{
"widgetName": "Icon1",
"isDeprecated": true,
"rightColumn": 5,
"displayName": "Icon",
"iconSVG": "/static/media/icon.31d6cfe0.svg",
"widgetId": "heq2edkb6s",
"topRow": 21,
"bottomRow": 25,
"parentRowSpace": 10,
"isVisible": true,
"type": "ICON_WIDGET",
"version": 1,
"hideCard": false,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"parentColumnSpace": 30.0625,
"leftColumn": 1,
"key": "q6apte987h"
},
{
"widgetName": "FilePicker1",
"displayName": "FilePicker",
"iconSVG": "/static/media/icon.7c5ad9c3.svg",
"topRow": 26,
"bottomRow": 30,
"parentRowSpace": 10,
"allowedFileTypes": [],
"type": "FILE_PICKER_WIDGET",
"hideCard": false,
"animateLoading": true,
"parentColumnSpace": 30.0625,
"leftColumn": 1,
"isDisabled": false,
"key": "0lvexvvl0g",
"isRequired": false,
"isDeprecated": true,
"rightColumn": 17,
"isDefaultClickDisabled": true,
"widgetId": "hiug3nerkb",
"isVisible": true,
"label": "Select Files",
"maxFileSize": 5,
"version": 1,
"fileDataType": "Base64",
"parentId": "0",
"selectedFiles": [],
"renderMode": "CANVAS",
"isLoading": false,
"files": [],
"maxNumFiles": 1
},
{
"widgetName": "MultiSelect1",
"displayName": "MultiSelect",
"iconSVG": "/static/media/icon.a3495809.svg",
"labelText": "Label",
"topRow": 31,
"bottomRow": 38,
"parentRowSpace": 10,
"labelWidth": 5,
"type": "MULTI_SELECT_WIDGET",
"serverSideFiltering": false,
"hideCard": false,
"defaultOptionValue": [
"GREEN"
],
"animateLoading": true,
"parentColumnSpace": 30.0625,
"leftColumn": 1,
"labelPosition": "Left",
"options": [
{
"label": "Blue",
"value": "BLUE"
},
{
"label": "Green",
"value": "GREEN"
},
{
"label": "Red",
"value": "RED"
}
],
"placeholderText": "Select option(s)",
"isDisabled": false,
"key": "05pyckdekd",
"isRequired": false,
"isDeprecated": true,
"rightColumn": 21,
"widgetId": "czlaz4dty2",
"isVisible": true,
"version": 1,
"parentId": "0",
"labelAlignment": "left",
"renderMode": "CANVAS",
"isLoading": false
},
{
"widgetName": "ProgressBar1",
"isCanvas": false,
"displayName": "Progress Bar",
"iconSVG": "/static/media/icon.9b0d7b96.svg",
"topRow": 44,
"bottomRow": 48,
"parentRowSpace": 10,
"type": "PROGRESSBAR_WIDGET",
"hideCard": false,
"fillColor": "#03B365",
"parentColumnSpace": 30.0625,
"leftColumn": 1,
"key": "wknrvlvi6b",
"showResult": false,
"isDeprecated": true,
"rightColumn": 29,
"widgetId": "bxn75b85v2",
"isVisible": true,
"steps": 1,
"version": 1,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"progress": 50,
"barType": "indeterminate"
},
{
"widgetName": "CircularProgress1",
"displayName": "Circular Progress",
"iconSVG": "/static/media/icon.d5418f48.svg",
"topRow": 49,
"bottomRow": 66,
"parentRowSpace": 10,
"type": "CIRCULAR_PROGRESS_WIDGET",
"hideCard": false,
"fillColor": "#03B365",
"animateLoading": true,
"parentColumnSpace": 30.0625,
"leftColumn": 1,
"shouldTruncate": false,
"key": "ztjmd8ec4a",
"showResult": true,
"isDeprecated": true,
"rightColumn": 17,
"widgetId": "5r48vbnl9d",
"counterClockWise": false,
"isVisible": true,
"shouldScroll": false,
"version": 1,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"progress": 65
}
]
}
}

View File

@ -0,0 +1,27 @@
const dsl = require("../../../../fixtures/deprecatedWidgets.json");
describe("Deprecation warning feature", function() {
before(() => {
cy.addDsl(dsl);
});
it("should have deprecation warning on all the deprecated widgets", function() {
cy.get(`#div-selection-0`).click({
force: true,
});
for (const widgets of dsl.dsl.children) {
cy.get(`#div-selection-0`).click({
force: true,
});
cy.get(`#${widgets.widgetId}`).click({
ctrlKey: true,
});
cy.get(`div[data-testid='t--selected']`).should("have.length", 1);
cy.get(`.t--deprecation-warning`).should("have.length", 1);
}
});
});

View File

@ -1032,15 +1032,6 @@ export const TEST_EMAIL_FAILURE = () => "Sending Test Email Failed";
export const DISCONNECT_AUTH_ERROR = () =>
"Cannot disconnect the only connected authentication method.";
export const MANDATORY_FIELDS_ERROR = () => "Mandatory fields cannot be empty";
//Reflow Beta Screen
export const REFLOW_BETA_CHECKBOX_LABEL = () =>
"Turn on new drag & drop experience";
export const REFLOW_INFO_CARD_HEADER = () => "New Drag & Drop Experience";
export const REFLOW_INFO_CARD_CONTENT_1 = () =>
"When dropping a new widget, other widgets now automatically move out of the way.";
export const REFLOW_INFO_CARD_CONTENT_2 = () =>
"Widgets next to the canvas edge will shrink to make space for the new widget.";
export const REFLOW_LEARN_MORE = () => "LEARN MORE";
//
export const WELCOME_FORM_NON_SUPER_USER_ROLE_DROPDOWN = () =>
"Tell us more about what you do at work?";
@ -1052,6 +1043,9 @@ export const QUERY_CONFIRMATION_MODAL_MESSAGE = () =>
export const ENTITY_EXPLORER_TITLE = () => "NAVIGATION";
export const MULTI_SELECT_PROPERTY_PANE_MESSAGE = () =>
`Select a widget to see it's properties`;
export const WIDGET_DEPRECATION_WARNING = (widgetName: string) =>
`A new version of the ${widgetName}widget is available. Upgrade to enjoy an enhanced experience.`;
export const WIDGET_DEPRECATION_WARNING_HEADER = () => "Stay Up-to-date";
export const LOCK_ENTITY_EXPLORER_MESSAGE = () => `Lock sidebar open`;
export const CLOSE_ENTITY_EXPLORER_MESSAGE = () => `Close sidebar`;

View File

@ -0,0 +1,76 @@
import React from "react";
import styled from "styled-components";
import Icon, { IconSize } from "components/ads/Icon";
type Props = {
backgroundColor: string;
className: string;
icon: string;
iconColor: string;
iconSize: IconSize;
messageHeader?: string;
message: string;
textColor: string;
};
const MessageContainer = styled.div<{
backgroundColor: string;
textColor: string;
}>`
display: flex;
padding: 8px;
margin-bottom: 8px;
flex-direction: row;
color: ${(props) => props.textColor};
background: ${(props) => props.backgroundColor};
}
`;
const StyledIcon = styled(Icon)`
padding: 10px;
cursor: default;
svg {
cursor: default;
}
`;
const MessageWrapper = styled.div`
display: flex;
flex-direction: column;
padding-left: 4px;
line-height: 16px;
`;
const MessageText = styled.p`
font-size: 13px;
font-weight: 400;
`;
const MessageHeader = styled.h2`
font-size: 14px;
font-weight: 600;
padding-bottom: 5px;
`;
export function BannerMessage(props: Props) {
return (
<MessageContainer
backgroundColor={props.backgroundColor}
className={props.className}
textColor={props.textColor}
>
<StyledIcon
fillColor={props.iconColor}
name={props.icon}
size={props.iconSize}
/>
<MessageWrapper>
{props.messageHeader && (
<MessageHeader>{props.messageHeader}</MessageHeader>
)}
<MessageText>{props.message}</MessageText>
</MessageWrapper>
</MessageContainer>
);
}

View File

@ -21,7 +21,7 @@ const StyledDiv = styled.div`
props.theme.colors.propertyPane.ctaBackgroundColor};
padding: ${(props) => props.theme.spaces[3]}px ${(props) =>
props.theme.spaces[7]}px;
margin: ${(props) => props.theme.spaces[2]}px 0px;
margin: ${(props) => props.theme.spaces[2]}px 0.75rem;
button:first-child {
margin-top: ${(props) => props.theme.spaces[2]}px;

View File

@ -77,9 +77,9 @@ export function PropertyControlsGenerator(
) {
const config = WidgetFactory.getWidgetPropertyPaneConfig(props.type);
return (
<>
<div className="px-3">
{generatePropertyControl(config as readonly PropertyPaneConfig[], props)}
</>
</div>
);
}

View File

@ -35,6 +35,7 @@ const TopLayer = styled.div`
display: flex;
flex: 1;
justify-content: space-between;
padding: 0 0.75rem;
.connection-dropdown {
box-shadow: none;

View File

@ -12,6 +12,15 @@ import PropertyPaneConnections from "./PropertyPaneConnections";
import CopyIcon from "remixicon-react/FileCopyLineIcon";
import DeleteIcon from "remixicon-react/DeleteBinLineIcon";
import { WidgetType } from "constants/WidgetConstants";
import { isWidgetDeprecated } from "../utils";
import { BannerMessage } from "components/ads/BannerMessage";
import { Colors } from "constants/Colors";
import { IconSize } from "components/ads";
import {
createMessage,
WIDGET_DEPRECATION_WARNING,
WIDGET_DEPRECATION_WARNING_HEADER,
} from "@appsmith/constants/messages";
// TODO(abhinav): The widget should add a flag in their configuration if they donot subscribe to data
// Widgets where we do not want to show the CTA
@ -97,6 +106,18 @@ function PropertyPaneView(
if (!widgetProperties) return null;
// Building Deprecation Messages
const isDeprecated = isWidgetDeprecated(widgetProperties.type);
const widgetDisplayName = widgetProperties.displayName
? `${widgetProperties.displayName} `
: "";
// generate messages
const deprecationMessage = createMessage(
WIDGET_DEPRECATION_WARNING,
widgetDisplayName,
);
const deprecationHeader = createMessage(WIDGET_DEPRECATION_WARNING_HEADER);
return (
<div
className="relative flex flex-col w-full pt-3 overflow-y-auto"
@ -111,7 +132,7 @@ function PropertyPaneView(
/>
<div
className="p-3 pb-24 overflow-x-hidden overflow-y-scroll t--property-pane-view"
className="pt-3 pb-24 overflow-x-hidden overflow-y-scroll t--property-pane-view"
data-guided-tour-id="property-pane"
>
{!doActionsExist && !hideConnectDataCTA && (
@ -122,7 +143,18 @@ function PropertyPaneView(
/>
)}
<PropertyPaneConnections widgetName={widgetProperties.widgetName} />
{isDeprecated && (
<BannerMessage
backgroundColor={Colors.WARNING_ORANGE}
className="t--deprecation-warning"
icon="warning-line"
iconColor={Colors.WARNING_SOLID}
iconSize={IconSize.XXXXL}
message={deprecationMessage}
messageHeader={deprecationHeader}
textColor={Colors.BROWN}
/>
)}
<PropertyControlsGenerator
id={widgetProperties.widgetId}
panel={panel}

View File

@ -3,7 +3,9 @@ import _, { debounce } from "lodash";
import { useMemo } from "react";
import ReactDOM from "react-dom";
import { useLocation } from "react-router";
import { WidgetType } from "constants/WidgetConstants";
import ResizeObserver from "resize-observer-polyfill";
import WidgetFactory from "utils/WidgetFactory";
export const draggableElement = (
id: string,
@ -234,3 +236,7 @@ export const useQuery = () => {
const { search } = useLocation();
return useMemo(() => new URLSearchParams(search), [search]);
};
export function isWidgetDeprecated(WidgetType: WidgetType) {
return !!WidgetFactory.widgetConfigMap.get(WidgetType)?.isDeprecated;
}

View File

@ -54,6 +54,7 @@ export const configureWidget = (config: WidgetConfiguration) => {
...config.defaults,
type: config.type,
hideCard: !!config.hideCard || !config.iconSVG,
isDeprecated: !!config.isDeprecated,
displayName: config.name,
key: generateReactKey(),
iconSVG: config.iconSVG,

View File

@ -156,29 +156,22 @@ export const ALL_WIDGETS_AND_CONFIG = [
[CheckboxWidget, CHECKBOX_WIDGET_CONFIG],
[RadioGroupWidget, RADIO_GROUP_WIDGET_CONFIG],
[ButtonWidget, BUTTON_WIDGET_CONFIG],
[DropdownWidget, DROPDOWN_WIDGET_CONFIG],
[ImageWidget, IMAGE_WIDGET_CONFIG],
[VideoWidget, VIDEO_WIDGET_CONFIG],
[TabsWidget, TABS_WIDGET_CONFIG],
[InputWidget, INPUT_WIDGET_CONFIG],
[ModalWidget, MODAL_WIDGET_CONFIG],
[ChartWidget, CHART_WIDGET_CONFIG],
[MapWidget, MAP_WIDGET_CONFIG],
[FilePickerWidget, FILEPICKER_WIDGET_CONFIG],
[RichTextEditorWidget, RICH_TEXT_EDITOR_WIDGET_CONFIG],
[DatePickerWidget, DATE_PICKER_WIDGET_CONFIG],
[DatePickerWidget2, DATE_PICKER_WIDGET_2_CONFIG],
[SwitchWidget, SWITCH_WIDGET_CONFIG],
[FormWidget, FORM_WIDGET_CONFIG],
[FormButtonWidget, FORM_BUTTON_WIDGET_CONFIG],
[IconWidget, ICON_WIDGET_CONFIG],
[ListWidget, LIST_WIDGET_CONFIG],
[RateWidget, RATE_WIDGET_CONFIG],
[IframeWidget, IFRAME_WIDGET_CONFIG],
[TabsMigratorWidget, TABS_MIGRATOR_WIDGET_CONFIG],
[DividerWidget, DIVIDER_WIDGET_CONFIG],
[MenuButtonWidget, MENU_BUTTON_WIDGET_CONFIG],
[MultiSelectWidget, MULTI_SELECT_WIDGET_CONFIG],
[IconButtonWidget, ICON_BUTTON_WIDGET_CONFIG],
[CheckboxGroupWidget, CHECKBOX_GROUP_WIDGET_CONFIG],
[FilePickerWidgetV2, FILEPICKER_WIDGET_V2_CONFIG],
@ -195,12 +188,21 @@ export const ALL_WIDGETS_AND_CONFIG = [
[MapChartWidget, MAP_CHART_WIDGET_CONFIG],
[SelectWidget, SELECT_WIDGET_CONFIG],
[MultiSelectWidgetV2, MULTI_SELECT_WIDGET_V2_CONFIG],
[CircularProgressWidget, CIRCULAR_PROGRESS_WIDGET_CONFIG],
[InputWidgetV2, INPUT_WIDGET_V2_CONFIG],
[PhoneInputWidget, PHONE_INPUT_WIDGET_V2_CONFIG],
[CurrencyInputWidget, CURRENCY_INPUT_WIDGET_V2_CONFIG],
[JSONFormWidget, JSON_FORM_WIDGET_CONFIG],
//Deprecated Widgets
[InputWidget, INPUT_WIDGET_CONFIG],
[DropdownWidget, DROPDOWN_WIDGET_CONFIG],
[DatePickerWidget, DATE_PICKER_WIDGET_CONFIG],
[IconWidget, ICON_WIDGET_CONFIG],
[FilePickerWidget, FILEPICKER_WIDGET_CONFIG],
[MultiSelectWidget, MULTI_SELECT_WIDGET_CONFIG],
[FormButtonWidget, FORM_BUTTON_WIDGET_CONFIG],
[ProgressWidget, PROGRESS_WIDGET_CONFIG],
[CircularProgressWidget, CIRCULAR_PROGRESS_WIDGET_CONFIG],
/*
* If a newly added widget works well inside the list widget,
* please add widget type in the List widget's allowed widget

View File

@ -6,6 +6,7 @@ export const CONFIG = {
type: Widget.getWidgetType(),
name: "Circular Progress",
hideCard: true,
isDeprecated: true,
iconSVG: IconSVG,
defaults: {
counterClockWise: false,

View File

@ -7,6 +7,7 @@ export const CONFIG = {
name: "DatePicker",
iconSVG: IconSVG,
hideCard: true,
isDeprecated: true,
needsMeta: true,
defaults: {
isDisabled: false,

View File

@ -9,6 +9,7 @@ export const CONFIG = {
iconSVG: IconSVG,
needsMeta: true,
hideCard: true,
isDeprecated: true,
defaults: {
rows: 7,
columns: 20,

View File

@ -8,6 +8,7 @@ export const CONFIG = {
iconSVG: IconSVG,
needsMeta: true,
hideCard: true,
isDeprecated: true,
defaults: {
rows: 4,
files: [],

View File

@ -6,6 +6,7 @@ export const CONFIG = {
name: "Icon",
iconSVG: IconSVG,
hideCard: true,
isDeprecated: true,
defaults: {
widgetName: "Icon",
rows: 4,

View File

@ -9,6 +9,7 @@ export const CONFIG = {
iconSVG: IconSVG,
needsMeta: true,
hideCard: true,
isDeprecated: true,
defaults: {
inputType: "TEXT",
rows: 4,

View File

@ -9,6 +9,7 @@ export const CONFIG = {
iconSVG: IconSVG,
needsMeta: true,
hideCard: true,
isDeprecated: true,
defaults: {
rows: 7,
columns: 20,

View File

@ -6,6 +6,7 @@ export const CONFIG = {
type: Widget.getWidgetType(),
name: "Progress Bar", // The display name which will be made in uppercase and show in the widgets panel ( can have spaces )
hideCard: true,
isDeprecated: true,
iconSVG: IconSVG,
needsMeta: false, // Defines if this widget adds any meta properties
isCanvas: false, // Defines if this widget has a canvas within in which we can drop other widgets

View File

@ -10,6 +10,7 @@ export interface WidgetConfiguration {
iconSVG?: string;
defaults: Partial<WidgetProps> & WidgetConfigProps;
hideCard?: boolean;
isDeprecated?: boolean;
isCanvas?: boolean;
needsMeta?: boolean;
features?: WidgetFeatures;