Skip to content

Commit

Permalink
hydrate widgets properties from session on drop
Browse files Browse the repository at this point in the history
  • Loading branch information
Pawan Kumar authored and Pawan Kumar committed Apr 25, 2024
1 parent 4b9dddc commit 152ac84
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 7 deletions.
20 changes: 17 additions & 3 deletions app/client/src/components/propertyControls/ButtonListControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,17 +216,31 @@ class ButtonListControl extends BaseControl<
};
}

// if the widget is a WDS_INLINE_BUTTONS_WIDGET, and button already have filled button variant in groupButtons,
// then we should add a secondary button ( outlined button ) instead of simple button
if (this.props.widgetProperties.type === "WDS_INLINE_BUTTONS_WIDGET") {
// if buttonVariant and buttonColor values ar present in session storage, then we should use those values
const buttonVariantSessionValue = sessionStorage.getItem(
"WDS_INLINE_BUTTONS_WIDGET.buttonVariant",
);
const buttonColorSessionValue = sessionStorage.getItem(
"WDS_INLINE_BUTTONS_WIDGET.buttonColor",
);

groupButtons[newGroupButtonId] = {
...groupButtons[newGroupButtonId],
buttonVariant: buttonVariantSessionValue || "filled",
buttonColor: buttonColorSessionValue || "accent",
};

// if the widget is a WDS_INLINE_BUTTONS_WIDGET, and button already have filled button variant in groupButtons,
// then we should add a secondary button ( outlined button ) instead of simple button
const filledButtonVariant = groupButtonsArray.find(
(groupButton: any) => groupButton.buttonVariant === "filled",
);

if (filledButtonVariant) {
groupButtons[newGroupButtonId] = {
...groupButtons[newGroupButtonId],
buttonVariant: "outlined",
buttonVariant: buttonVariantSessionValue || "outlined",
};
}
}
Expand Down
2 changes: 2 additions & 0 deletions app/client/src/constants/PropertyControlConstants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export interface PropertyPaneControlConfig {
*/
controlConfig?: Record<string, unknown>;
defaultValue?: unknown;
/** used to mark a property as reusable so that it can be reused in next dropping widget */
isReusable?: boolean;
}

interface ValidationConfigParams {
Expand Down
12 changes: 10 additions & 2 deletions app/client/src/pages/Editor/PropertyPane/PropertyControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import type { PropertyUpdates } from "WidgetProvider/constants";
import { getIsOneClickBindingOptionsVisibility } from "selectors/oneClickBindingSelectors";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { savePropertyInSessionStorageIfRequired } from "./helpers";

const ResetIcon = importSvg(
async () => import("assets/icons/control/undo_2.svg"),
Expand Down Expand Up @@ -574,6 +575,13 @@ const PropertyControl = memo((props: Props) => {
// updating properties of a widget(s) should be done only once when property value changes.
// to make sure dsl updates are atomic which is a necessity for undo/redo.
onBatchUpdatePropertiesOfMultipleWidgets(allPropertiesToUpdates);

savePropertyInSessionStorageIfRequired({
isReusable: !!props.isReusable,
widgetProperties,
propertyName,
propertyValue,
});
}
},
[
Expand Down Expand Up @@ -860,8 +868,8 @@ const PropertyControl = memo((props: Props) => {
const JSToggleTooltip = isToggleDisabled
? JS_TOGGLE_DISABLED_MESSAGE
: !isDynamic
? JS_TOGGLE_SWITCH_JS_MESSAGE
: "";
? JS_TOGGLE_SWITCH_JS_MESSAGE
: "";

try {
return (
Expand Down
38 changes: 38 additions & 0 deletions app/client/src/pages/Editor/PropertyPane/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Callout } from "design-system";
import React from "react";
import WidgetFactory from "WidgetProvider/factory";
import type { WidgetCallout } from "WidgetProvider/constants";
import { isDynamicValue } from "utils/DynamicBindingUtils";

export function useSearchText(initialVal: string) {
const [searchText, setSearchText] = useState(initialVal);
Expand Down Expand Up @@ -127,3 +128,40 @@ export function renderWidgetCallouts(props: WidgetProps): JSX.Element[] {
return [];
}
}

/**
* saves property value incase it is a reusable property in the session storage so that we can re-use
* the property value when we create widget on drop.
*
* Note: these values that we are storing will be used in widgetAddtionSaga to hydrate the widget properties when
* we create widget on drop
*/
export function savePropertyInSessionStorageIfRequired(props: {
isReusable: boolean;
widgetProperties: any;
propertyName: string;
propertyValue: string;
}) {
const { isReusable, propertyName, propertyValue, widgetProperties } = props;

if (isReusable && isDynamicValue(propertyValue) === false) {
let widgetType = widgetProperties.type;
let widgetPropertyName = propertyName;

// in case of type is WDS_ICON_BUTTON_WIDGET, we need to use key WDS_BUTTON_WIDGET, reason being
// we want to reuse the property values of icon button for button as well when we create button widget on drop
if (widgetType === "WDS_ICON_BUTTON_WIDGET") {
widgetType = "WDS_BUTTON_WIDGET";
}

// in case of type is WDS_INLINE_BUTTONS_WIDGET, we want to just store the property that is being changed, not the whole property path
if (widgetType === "WDS_INLINE_BUTTONS_WIDGET") {
widgetPropertyName = propertyName.split(".").pop() as string;
}

sessionStorage.setItem(
`${widgetType}.${widgetPropertyName}`,
propertyValue,
);
}
}
3 changes: 1 addition & 2 deletions app/client/src/pages/Editor/widgetSidebar/WidgetCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ function WidgetCard(props: CardProps) {
};

const type = `${props.details.type.split("_").join("").toLowerCase()}`;
const className = `t--widget-card-draggable t--widget-card-draggable-${type}
}`;
const className = `t--widget-card-draggable t--widget-card-draggable-${type}`;

return (
<Wrapper
Expand Down
32 changes: 32 additions & 0 deletions app/client/src/sagas/WidgetAdditionSagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ function* getChildWidgetProps(
]);
const themeDefaultConfig =
WidgetFactory.getWidgetStylesheetConfigMap(type) || {};
const widgetSessionValues = getWidgetSessionValues(type);
const mainCanvasWidth: number = yield select(getCanvasWidth);
const isMobile: boolean = yield select(getIsAutoLayoutMobileBreakPoint);

Expand Down Expand Up @@ -169,6 +170,7 @@ function* getChildWidgetProps(
widgetId: newWidgetId,
renderMode: RenderModes.CANVAS,
...themeDefaultConfig,
...widgetSessionValues,
};

const { minWidth } = getWidgetMinMaxDimensionsInPixel(
Expand Down Expand Up @@ -787,3 +789,33 @@ export default function* widgetAdditionSagas() {
takeEvery(ReduxActionTypes.WIDGET_ADD_NEW_TAB_CHILD, addNewTabChildSaga),
]);
}

/**
* retrieves the values from session storage for the widget properties
* for hydration of the widget when we create widget on drop
*/
export function getWidgetSessionValues(type: string) {
// we don't need to hydrate widget for following widgets
if (["WDS_INLINE_BUTTONS_WIDGET"].includes(type)) return;

let widgetType = type;
const configMap = WidgetFactory.widgetConfigMap.get(type);
const widgetSessionValues: any = {};

// in case we are dropping WDS_ICON_BUTTON_WIDGET, we want to reuse the values of BUTTON_WIDGET
if (type === "WDS_ICON_BUTTON_WIDGET") {
widgetType = "WDS_BUTTON_WIDGET";
}

for (const key in configMap) {
if (configMap[key]) {
const valueFromSession = sessionStorage.getItem(`${widgetType}.${key}`);

if (valueFromSession) {
widgetSessionValues[key] = valueFromSession;
}
}
}

return widgetSessionValues;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const propertyPaneStyleConfig = [
isJSConvertible: true,
isBindProperty: true,
isTriggerProperty: false,
isReusable: true,
validation: {
type: ValidationTypes.TEXT,
params: {
Expand All @@ -40,6 +41,7 @@ export const propertyPaneStyleConfig = [
isJSConvertible: true,
isBindProperty: true,
isTriggerProperty: false,
isReusable: true,
validation: {
type: ValidationTypes.TEXT,
params: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const propertyPaneStyleConfig = [
isJSConvertible: true,
isBindProperty: true,
isTriggerProperty: false,
isReusable: true,
validation: {
type: ValidationTypes.TEXT,
params: {
Expand All @@ -40,6 +41,7 @@ export const propertyPaneStyleConfig = [
isJSConvertible: true,
isBindProperty: true,
isTriggerProperty: false,
isReusable: true,
validation: {
type: ValidationTypes.TEXT,
params: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export const propertyPaneContentConfig = [
isJSConvertible: true,
isBindProperty: true,
isTriggerProperty: false,
isReusable: true,
validation: {
type: ValidationTypes.TEXT,
params: {
Expand All @@ -125,6 +126,7 @@ export const propertyPaneContentConfig = [
isJSConvertible: true,
isBindProperty: true,
isTriggerProperty: false,
isReusable: true,
validation: {
type: ValidationTypes.TEXT,
params: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const propertyPaneStyleConfig = [
isJSConvertible: true,
isBindProperty: true,
isTriggerProperty: false,
isReusable: true,
validation: {
type: ValidationTypes.TEXT,
params: {
Expand Down Expand Up @@ -69,6 +70,7 @@ export const propertyPaneStyleConfig = [
isJSConvertible: true,
isBindProperty: true,
isTriggerProperty: false,
isReusable: true,
validation: {
type: ValidationTypes.TEXT,
params: {
Expand All @@ -95,6 +97,7 @@ export const propertyPaneStyleConfig = [
isJSConvertible: true,
isBindProperty: true,
isTriggerProperty: false,
isReusable: true,
validation: { type: ValidationTypes.TEXT },
},
],
Expand Down

0 comments on commit 152ac84

Please sign in to comment.