Skip to content
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

12/11 Daily Promotion #37332

Merged
merged 5 commits into from
Nov 12, 2024
Merged
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
7 changes: 7 additions & 0 deletions app/client/src/ce/constants/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2522,3 +2522,10 @@ export const JS_EDITOR_SETTINGS = {
TITLE: () => "Settings",
ON_LOAD_TITLE: () => "Choose the functions to run on page load",
};

export const CUSTOM_WIDGET_BUILDER_TAB_TITLE = {
AI: () => "AI",
HTML: () => "HTML",
STYLE: () => "Style",
JS: () => "Javascript",
};
2 changes: 2 additions & 0 deletions app/client/src/ce/entities/FeatureFlag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const FEATURE_FLAG = {
"release_ide_datasource_selector_enabled",
release_table_custom_loading_state_enabled:
"release_table_custom_loading_state_enabled",
release_custom_widget_ai_builder: "release_custom_widget_ai_builder",
} as const;

export type FeatureFlag = keyof typeof FEATURE_FLAG;
Expand Down Expand Up @@ -77,6 +78,7 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = {
release_ide_animations_enabled: false,
release_ide_datasource_selector_enabled: false,
release_table_custom_loading_state_enabled: false,
release_custom_widget_ai_builder: false,
};

export const AB_TESTING_EVENT_KEYS = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import React, {
useCallback,
useContext,
useEffect,
useMemo,
useRef,
} from "react";
import type { ContentProps } from "../CodeEditors/types";
import { CustomWidgetBuilderContext } from "../..";
import {
CUSTOM_WIDGET_AI_BOT_MESSAGE_RESPONSE_DEBOUNCE_TIMEOUT,
CUSTOM_WIDGET_AI_BOT_URL,
CUSTOM_WIDGET_AI_CHAT_TYPE,
CUSTOM_WIDGET_AI_INITIALISED_MESSAGE,
} from "../../constants";
import { isObject } from "lodash";

export const ChatBot = (props: ContentProps) => {
const ref = useRef<HTMLIFrameElement>(null);
const lastUpdateFromBot = useRef<number>(0);
const { bulkUpdate, parentEntityId, uncompiledSrcDoc, widgetId } = useContext(
CustomWidgetBuilderContext,
);

const handleSrcDocUpdates = useCallback(() => {
// Don't send updates back to bot if the last update came from the bot within the last 100ms
if (
Date.now() - lastUpdateFromBot.current <
CUSTOM_WIDGET_AI_BOT_MESSAGE_RESPONSE_DEBOUNCE_TIMEOUT
) {
return;
}

// Send src doc to the chatbot iframe
if (ref.current && ref.current.contentWindow && uncompiledSrcDoc) {
ref.current.contentWindow.postMessage(
{
html_code: uncompiledSrcDoc.html,
css_code: uncompiledSrcDoc.css,
js_code: uncompiledSrcDoc.js,
chatType: CUSTOM_WIDGET_AI_CHAT_TYPE,
},
"*",
);
}
}, [uncompiledSrcDoc]);

const updateContents = useCallback(
(
event: MessageEvent<
string | { html_code?: string; css_code?: string; js_code?: string }
>,
) => {
const iframeWindow =
ref.current?.contentWindow || ref.current?.contentDocument?.defaultView;

// Accept messages only from the current iframe
if (event.source !== iframeWindow) return;

if (event.data === CUSTOM_WIDGET_AI_INITIALISED_MESSAGE) {
handleSrcDocUpdates();

return;
}

if (!bulkUpdate) return;

if (isObject(event.data)) {
lastUpdateFromBot.current = Date.now();

bulkUpdate({
html: event.data.html_code || "",
css: event.data.css_code || "",
js: event.data.js_code || "",
});
}
},
[bulkUpdate, handleSrcDocUpdates],
);

useEffect(
function addEventListenerForBotUpdates() {
// add a listener to update the contents
window.addEventListener("message", updateContents, false);

// clean up
return () => window.removeEventListener("message", updateContents, false);
},
[updateContents],
);

useEffect(handleSrcDocUpdates, [handleSrcDocUpdates]);

const instanceId = `${widgetId}-${parentEntityId}`;

const srcUrl = useMemo(() => {
return CUSTOM_WIDGET_AI_BOT_URL(instanceId);
}, [instanceId]);

return (
<iframe height={`${props.height}px`} ref={ref} src={srcUrl} width="100%" />
);
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from "react";
import styles from "./styles.module.css";
import WidgetName from "./widgetName";
import LayoutControls from "./layoutControls";
import ReferenceTrigger from "./referenceTrigger";
import { CodeTemplates } from "./CodeTemplates";

Expand All @@ -11,7 +10,6 @@ export default function Header() {
<div className={styles.headerControlsLeft}>
<WidgetName />
<CodeTemplates />
<LayoutControls />
</div>
<div className={styles.headerControlsRight}>
<ReferenceTrigger />
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import styles from "./styles.module.css";
import { Tab, TabPanel, Tabs, TabsList } from "@appsmith/ads";
import type { ContentProps } from "../../CodeEditors/types";
import useLocalStorageState from "utils/hooks/useLocalStorageState";
import classNames from "classnames";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
import { CUSTOM_WIDGET_BUILDER_TABS } from "../../../constants";

interface Props {
tabs: Array<{
Expand All @@ -17,9 +21,15 @@ const LOCAL_STORAGE_KEYS = "custom-widget-layout-tabs-state";
export default function TabLayout(props: Props) {
const { tabs } = props;

const isDefaultAITab = useFeatureFlag(
FEATURE_FLAG.release_custom_widget_ai_builder,
);

const [selectedTab, setSelectedTab] = useLocalStorageState<string>(
LOCAL_STORAGE_KEYS,
tabs[0].title,
isDefaultAITab
? CUSTOM_WIDGET_BUILDER_TABS.AI
: CUSTOM_WIDGET_BUILDER_TABS.JS,
);

useEffect(() => {
Expand Down Expand Up @@ -88,7 +98,10 @@ export default function TabLayout(props: Props) {
</TabsList>
{tabs.map((tab) => (
<TabPanel
className={styles.tabPanel}
className={classNames(styles.tabPanel, {
"data-[state=inactive]:hidden": selectedTab !== tab.title,
})}
forceMount
key={tab.title}
value={tab.title}
>
Expand Down
Loading
Loading