Skip to content

Commit

Permalink
chore: Refactor WDS custom widget (#38038)
Browse files Browse the repository at this point in the history
/ok-to-test tags="@tag.Widget"

Fixes #38028 

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

- **New Features**
- Introduced a new `IframeMessenger` class for improved communication
between the parent window and iframe.
- Added `onConsole`, `onTriggerEvent`, and `onUpdateModel` props to the
`Preview` component for enhanced event handling.
- Streamlined HTML template generation with the `createHtmlTemplate`
function.

- **Bug Fixes**
- Removed unnecessary UI-related event handling from the widget,
simplifying the communication structure.
- Updated event names in template files from `"onReset"` to
`"onResetClick"` for clarity.

- **Refactor**
	- Renamed `CustomComponent` to `CustomWidgetComponent` for clarity.
	- Modularized message handling logic in the `CustomWidgetComponent`.
- Refactored the `defaultApp.ts` to use dynamic template data instead of
hardcoded values.

- **Style**
	- Updated CSS for the `.container` class to enhance layout consistency.

- **Tests**
	- Simplified test assertions in the `customWidgetscript` test suite.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/12234751176>
> Commit: eb55fbd
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=12234751176&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.Widget`
> Spec:
> <hr>Mon, 09 Dec 2024 12:47:13 UTC
<!-- end of auto-generated comment: Cypress test results  -->
  • Loading branch information
jsartisan authored Dec 10, 2024
1 parent e754e48 commit 8198819
Show file tree
Hide file tree
Showing 19 changed files with 348 additions and 442 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { IframeMessage } from "../types";
import { EVENTS } from "./customWidgetscript";

export class IframeMessenger {
private iframe: HTMLIFrameElement;

constructor(iframe: HTMLIFrameElement) {
this.iframe = iframe;
}

handleMessage = (
event: MessageEvent,
handlers: Record<string, (data: Record<string, unknown>) => void>,
) => {
const iframeWindow =
this.iframe.contentWindow || this.iframe.contentDocument?.defaultView;

// Without this check, malicious scripts from other windows could inject
// unauthorized messages into our application, potentially leading to data
// breaches or unauthorized state modifications
if (event.source !== iframeWindow) return;

// We send an acknowledgement message for every event to ensure reliable communication
// between the parent window and iframe. This helps in maintaining message ordering
// and preventing race conditions.
this.acknowledgeMessage(event.data);

const handler = handlers[event.data.type];

if (handler) {
handler(event.data.data);
}
};

private acknowledgeMessage(message: IframeMessage) {
this.postMessage({
type: EVENTS.CUSTOM_WIDGET_MESSAGE_RECEIVED_ACK,
key: message.key,
success: true,
});
}

postMessage(message: IframeMessage) {
this.iframe.contentWindow?.postMessage(message, "*");
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// @ts-expect-error - Type error due to raw loader
import css from "!!raw-loader!./reset.css";

// @ts-expect-error - Type error due to raw loader
import script from "!!raw-loader!./customWidgetscript.js";

// @ts-expect-error - Type error due to raw loader
import appsmithConsole from "!!raw-loader!./appsmithConsole.js";

interface CreateHtmlTemplateProps {
cssTokens: string;
onConsole: boolean;
srcDoc: { html: string; js: string; css: string };
}

export const createHtmlTemplate = (props: CreateHtmlTemplateProps) => {
const { cssTokens, onConsole, srcDoc } = props;

return `<html>
<head>
<style>${css}</style>
<style data-appsmith-theme>${cssTokens}</style>
</head>
<body>
${onConsole ? `<script type="text/javascript">${appsmithConsole}</script>` : ""}
<script type="module">
${script}
main();
</script>
${srcDoc.html}
<script type="module">${srcDoc.js}</script>
<style>${srcDoc.css}</style>
</body>
</html>`;
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export const EVENTS = {
CUSTOM_WIDGET_UPDATE_MODEL: "CUSTOM_WIDGET_UPDATE_MODEL",
CUSTOM_WIDGET_TRIGGER_EVENT: "CUSTOM_WIDGET_TRIGGER_EVENT",
CUSTOM_WIDGET_MODEL_CHANGE: "CUSTOM_WIDGET_MODEL_CHANGE",
CUSTOM_WIDGET_UI_CHANGE: "CUSTOM_WIDGET_UI_CHANGE",
CUSTOM_WIDGET_MESSAGE_RECEIVED_ACK: "CUSTOM_WIDGET_MESSAGE_RECEIVED_ACK",
CUSTOM_WIDGET_CONSOLE_EVENT: "CUSTOM_WIDGET_CONSOLE_EVENT",
CUSTOM_WIDGET_THEME_UPDATE: "CUSTOM_WIDGET_THEME_UPDATE",
Expand Down Expand Up @@ -119,7 +118,6 @@ export function main() {
* Variables to hold the subscriber functions
*/
const modelSubscribers = [];
const uiSubscribers = [];
const themeSubscribers = [];
/*
* Variables to hold ready function and state
Expand All @@ -139,15 +137,12 @@ export function main() {
// Callback for when the READY_ACK message is received
channel.onMessage(EVENTS.CUSTOM_WIDGET_READY_ACK, (event) => {
window.appsmith.model = event.model;
window.appsmith.ui = event.ui;
window.appsmith.theme = event.theme;
window.appsmith.mode = event.mode;
heightObserver.observe(window.document.body);

// Subscribe to model and UI changes
window.appsmith.onModelChange(generateAppsmithCssVariables("model"));
window.appsmith.onUiChange(generateAppsmithCssVariables("ui"));
window.appsmith.onThemeChange(generateAppsmithCssVariables("theme"));

// Set the widget as ready
isReady = true;
Expand All @@ -170,18 +165,6 @@ export function main() {
});
}
});
// Callback for when UI_CHANGE message is received
channel.onMessage(EVENTS.CUSTOM_WIDGET_UI_CHANGE, (event) => {
if (event.ui) {
const prevUi = window.appsmith.ui;

window.appsmith.ui = event.ui;
// Notify UI subscribers
uiSubscribers.forEach((fn) => {
fn(event.ui, prevUi);
});
}
});

channel.onMessage(EVENTS.CUSTOM_WIDGET_THEME_UPDATE, (event) => {
if (event.theme) {
Expand Down Expand Up @@ -235,23 +218,6 @@ export function main() {
}
};
},
onUiChange: (fn) => {
if (typeof fn !== "function") {
throw new Error("onUiChange expects a function as parameter");
}

uiSubscribers.push(fn);
fn(window.appsmith.ui);

return () => {
// Unsubscribe from UI changes
const index = uiSubscribers.indexOf(fn);

if (index > -1) {
uiSubscribers.splice(index, 1);
}
};
},
onModelChange: (fn) => {
if (typeof fn !== "function") {
throw new Error("onModelChange expects a function as parameter");
Expand Down Expand Up @@ -296,7 +262,6 @@ export function main() {
});
},
model: {},
ui: {},
onReady: (fn) => {
if (typeof fn !== "function") {
throw new Error("onReady expects a function as parameter");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,6 @@ describe("CustomWidgetScript", () => {
model: {
test: 1,
},
ui: {
width: 1,
height: 2,
},
mode: "test",
theme: {
color: "#fff",
Expand All @@ -182,11 +178,6 @@ describe("CustomWidgetScript", () => {
test: 1,
});

expect(window.appsmith.ui).toEqual({
width: 1,
height: 2,
});

expect(handler).toHaveBeenCalled();
});

Expand Down
Loading

0 comments on commit 8198819

Please sign in to comment.