From ee9e6c09bdd2b9c071198dc986ae111d6f0967aa Mon Sep 17 00:00:00 2001 From: Ramiro Medina <64783088+ramedina86@users.noreply.github.com> Date: Fri, 23 Aug 2024 11:26:56 +0000 Subject: [PATCH 01/30] feat: Feature flags --- src/ui/src/builder/BuilderHeader.vue | 21 +++++++++++++++++---- src/ui/src/core/index.ts | 7 +++++++ src/writer/app_runner.py | 3 ++- src/writer/core.py | 1 + src/writer/serve.py | 6 ++++-- src/writer/ss_types.py | 2 ++ tests/backend/test_serve.py | 16 ++++++++++++++++ tests/backend/testapp/main.py | 2 ++ 8 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/ui/src/builder/BuilderHeader.vue b/src/ui/src/builder/BuilderHeader.vue index d2bae0061..34e0a22a1 100644 --- a/src/ui/src/builder/BuilderHeader.vue +++ b/src/ui/src/builder/BuilderHeader.vue @@ -82,16 +82,29 @@ const animate = () => { }; const syncHealthStatus = () => { + let s = ""; + const featureFlags = wf.getFeatureFlags(); + switch (wf.syncHealth.value) { case "offline": - return "Offline. Not syncing."; + s += "Offline. Not syncing."; + break; case "connected": - return "Online. Syncing..."; + s += "Online. Syncing..."; + break; case "idle": - return "Sync not initialised."; + s += "Sync not initialised."; + break; case "suspended": - return "Sync suspended."; + s += "Sync suspended."; + break; + } + + if (featureFlags.length > 0) { + s += ` Feature flags: ${featureFlags.join(", ")}`; } + + return s; }; function showStateExplorer() { diff --git a/src/ui/src/core/index.ts b/src/ui/src/core/index.ts index 04c434292..e9b0ff906 100644 --- a/src/ui/src/core/index.ts +++ b/src/ui/src/core/index.ts @@ -24,6 +24,7 @@ export function generateCore() { let sessionId: string = null; const sessionTimestamp: Ref = ref(null); const mode: Ref<"run" | "edit"> = ref(null); + const featureFlags: Ref = ref([]); const runCode: Ref = ref(null); const components: Ref = ref({}); const userFunctions: Ref = ref([]); @@ -98,6 +99,7 @@ export function generateCore() { collateMail(initData.mail); sessionId = initData.sessionId; sessionTimestamp.value = new Date().getTime(); + featureFlags.value = initData.featureFlags; // Only returned for edit (Builder) mode @@ -567,6 +569,10 @@ export function generateCore() { return userState.value; } + function getFeatureFlags() { + return featureFlags.value; + } + const core = { webSocket, syncHealth, @@ -594,6 +600,7 @@ export function generateCore() { getSessionTimestamp, getUserState, isChildOf, + getFeatureFlags, }; return core; diff --git a/src/writer/app_runner.py b/src/writer/app_runner.py index a6a35738b..f91b7b06e 100644 --- a/src/writer/app_runner.py +++ b/src/writer/app_runner.py @@ -150,7 +150,8 @@ def _handle_session_init(self, payload: InitSessionRequestPayload) -> InitSessio sessionId=session.session_id, mail=session.session_state.mail, components=session.session_component_tree.to_dict(), - userFunctions=self._get_user_functions() + userFunctions=self._get_user_functions(), + featureFlags=writer.Config.feature_flags ) session.session_state.clear_mail() diff --git a/src/writer/core.py b/src/writer/core.py index 7502582ce..cbfe02ac6 100644 --- a/src/writer/core.py +++ b/src/writer/core.py @@ -131,6 +131,7 @@ class Config: is_mail_enabled_for_log: bool = False mode: str = "run" logger: Optional[logging.Logger] = None + feature_flags = [] @dataclasses.dataclass class MutationSubscription: diff --git a/src/writer/serve.py b/src/writer/serve.py index f52611344..f22b6dff0 100644 --- a/src/writer/serve.py +++ b/src/writer/serve.py @@ -149,7 +149,8 @@ def _get_run_starter_pack(payload: InitSessionResponsePayload): mail=payload.mail, components=payload.components, userFunctions=payload.userFunctions, - extensionPaths=cached_extension_paths + extensionPaths=cached_extension_paths, + featureFlags=payload.featureFlags ) def _get_edit_starter_pack(payload: InitSessionResponsePayload): @@ -163,7 +164,8 @@ def _get_edit_starter_pack(payload: InitSessionResponsePayload): components=payload.components, userFunctions=payload.userFunctions, runCode=run_code, - extensionPaths=cached_extension_paths + extensionPaths=cached_extension_paths, + featureFlags=payload.featureFlags ) @app.get("/api/health") diff --git a/src/writer/ss_types.py b/src/writer/ss_types.py index c7e65d9e8..442a0f3d1 100644 --- a/src/writer/ss_types.py +++ b/src/writer/ss_types.py @@ -43,6 +43,7 @@ class InitResponseBody(BaseModel): components: Dict userFunctions: List[Dict] extensionPaths: List + featureFlags: List[str] class InitResponseBodyRun(InitResponseBody): @@ -129,6 +130,7 @@ class InitSessionResponsePayload(BaseModel): mail: List userFunctions: List[Dict] components: Dict + featureFlags: List[str] class InitSessionResponse(AppProcessServerResponse): diff --git a/tests/backend/test_serve.py b/tests/backend/test_serve.py index f5b0514a7..c617de37e 100644 --- a/tests/backend/test_serve.py +++ b/tests/backend/test_serve.py @@ -169,3 +169,19 @@ def test_server_setup_hook_is_ignored_when_its_disabled(self): with fastapi.testclient.TestClient(asgi_app) as client: res = client.get("/probes/healthcheck") assert res.status_code == 404 + + def test_feature_flags(self): + """ + This test verifies that feature flags are carried to the frontend. + + """ + asgi_app: fastapi.FastAPI = writer.serve.get_asgi_app( + test_app_dir, "run") + with fastapi.testclient.TestClient(asgi_app) as client: + res = client.post("/api/init", json={ + "proposedSessionId": None + }, headers={ + "Content-Type": "application/json" + }) + feature_flags = res.json().get("featureFlags") + assert feature_flags == ["flag_one", "flag_two"] \ No newline at end of file diff --git a/tests/backend/testapp/main.py b/tests/backend/testapp/main.py index 53df2ac09..7742d84b9 100644 --- a/tests/backend/testapp/main.py +++ b/tests/backend/testapp/main.py @@ -9,6 +9,8 @@ import writer as wf import writer.core +writer.Config.feature_flags.append("flag_one") +writer.Config.feature_flags.append("flag_two") @wf.middleware() def my_middleware(state): From 5d55479e1e6af4452e5559cca270026a87d9ca1e Mon Sep 17 00:00:00 2001 From: Ramiro Medina <64783088+ramedina86@users.noreply.github.com> Date: Fri, 23 Aug 2024 11:35:32 +0000 Subject: [PATCH 02/30] fix: Type --- src/writer/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/writer/core.py b/src/writer/core.py index cbfe02ac6..ef58c63a9 100644 --- a/src/writer/core.py +++ b/src/writer/core.py @@ -131,7 +131,7 @@ class Config: is_mail_enabled_for_log: bool = False mode: str = "run" logger: Optional[logging.Logger] = None - feature_flags = [] + feature_flags: list[str] = [] @dataclasses.dataclass class MutationSubscription: From 0ae795abda80446ab32e57da334d67a9119ffe6d Mon Sep 17 00:00:00 2001 From: Ramiro Medina <64783088+ramedina86@users.noreply.github.com> Date: Fri, 23 Aug 2024 18:02:56 +0200 Subject: [PATCH 03/30] Update src/ui/src/core/index.ts Co-authored-by: Alexandre Rousseau --- src/ui/src/core/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/src/core/index.ts b/src/ui/src/core/index.ts index e9b0ff906..1ad28604b 100644 --- a/src/ui/src/core/index.ts +++ b/src/ui/src/core/index.ts @@ -24,7 +24,7 @@ export function generateCore() { let sessionId: string = null; const sessionTimestamp: Ref = ref(null); const mode: Ref<"run" | "edit"> = ref(null); - const featureFlags: Ref = ref([]); + const featureFlags = shallowRef([]); const runCode: Ref = ref(null); const components: Ref = ref({}); const userFunctions: Ref = ref([]); From dda21c344a88d3b8e23ae95bf20cdc0a425aaa49 Mon Sep 17 00:00:00 2001 From: Ramiro Medina <64783088+ramedina86@users.noreply.github.com> Date: Fri, 23 Aug 2024 18:03:33 +0200 Subject: [PATCH 04/30] Update src/ui/src/core/index.ts Co-authored-by: Alexandre Rousseau --- src/ui/src/core/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/src/core/index.ts b/src/ui/src/core/index.ts index 1ad28604b..e6ec1a08d 100644 --- a/src/ui/src/core/index.ts +++ b/src/ui/src/core/index.ts @@ -600,7 +600,7 @@ export function generateCore() { getSessionTimestamp, getUserState, isChildOf, - getFeatureFlags, + featureFlags: readonly(featureFlags), }; return core; From a1d7c501cbd00e1e78a31a2a8ea25ec2411d135b Mon Sep 17 00:00:00 2001 From: Ramiro Medina <64783088+ramedina86@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:15:08 +0000 Subject: [PATCH 05/30] chore: Changes to support Alex's suggestions --- apps/hello/main.py | 3 +++ src/ui/src/builder/BuilderHeader.vue | 6 ++---- src/ui/src/core/index.ts | 6 +----- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/apps/hello/main.py b/apps/hello/main.py index fb11ecac0..72c40dac2 100644 --- a/apps/hello/main.py +++ b/apps/hello/main.py @@ -8,6 +8,9 @@ # EVENT HANDLERS +wf.Config.feature_flags.append("dog") +wf.Config.feature_flags.append("duck") + def handle_timer_tick(state: WriterState): df = state["random_df"] for i in range(5): diff --git a/src/ui/src/builder/BuilderHeader.vue b/src/ui/src/builder/BuilderHeader.vue index 34e0a22a1..8e3f90e4c 100644 --- a/src/ui/src/builder/BuilderHeader.vue +++ b/src/ui/src/builder/BuilderHeader.vue @@ -83,8 +83,6 @@ const animate = () => { const syncHealthStatus = () => { let s = ""; - const featureFlags = wf.getFeatureFlags(); - switch (wf.syncHealth.value) { case "offline": s += "Offline. Not syncing."; @@ -100,8 +98,8 @@ const syncHealthStatus = () => { break; } - if (featureFlags.length > 0) { - s += ` Feature flags: ${featureFlags.join(", ")}`; + if (wf.featureFlags.value.length > 0) { + s += ` Feature flags: ${wf.featureFlags.value.join(", ")}`; } return s; diff --git a/src/ui/src/core/index.ts b/src/ui/src/core/index.ts index e6ec1a08d..e9c54384a 100644 --- a/src/ui/src/core/index.ts +++ b/src/ui/src/core/index.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/ban-types */ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { ref, Ref } from "vue"; +import { readonly, ref, Ref, shallowRef } from "vue"; import { Component, ComponentMap, @@ -569,10 +569,6 @@ export function generateCore() { return userState.value; } - function getFeatureFlags() { - return featureFlags.value; - } - const core = { webSocket, syncHealth, From 35bd4a91a6c195a4c495ae3396c0157f5b499c89 Mon Sep 17 00:00:00 2001 From: Ramiro Medina <64783088+ramedina86@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:23:31 +0000 Subject: [PATCH 06/30] fix: Remove test code --- apps/hello/main.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/hello/main.py b/apps/hello/main.py index 72c40dac2..fb11ecac0 100644 --- a/apps/hello/main.py +++ b/apps/hello/main.py @@ -8,9 +8,6 @@ # EVENT HANDLERS -wf.Config.feature_flags.append("dog") -wf.Config.feature_flags.append("duck") - def handle_timer_tick(state: WriterState): df = state["random_df"] for i in range(5): From 249db8d0677d3ec782a991f44c3fd9ce08c6c579 Mon Sep 17 00:00:00 2001 From: Dmitry Mozolevsky Date: Sun, 25 Aug 2024 19:33:30 -0700 Subject: [PATCH 07/30] fix: getting the BaseControlBar import to AnnotatedText component --- src/ui/src/core_components/content/CoreAnnotatedText.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/src/core_components/content/CoreAnnotatedText.vue b/src/ui/src/core_components/content/CoreAnnotatedText.vue index 6223fff75..64e2808dd 100644 --- a/src/ui/src/core_components/content/CoreAnnotatedText.vue +++ b/src/ui/src/core_components/content/CoreAnnotatedText.vue @@ -29,6 +29,7 @@ +../base/BaseContainer.vue diff --git a/src/ui/src/core_components/layout/CoreSteps.vue b/src/ui/src/components/core/layout/CoreSteps.vue similarity index 91% rename from src/ui/src/core_components/layout/CoreSteps.vue rename to src/ui/src/components/core/layout/CoreSteps.vue index 765273061..e521135cc 100644 --- a/src/ui/src/core_components/layout/CoreSteps.vue +++ b/src/ui/src/components/core/layout/CoreSteps.vue @@ -25,7 +25,7 @@ import { buttonTextColor, buttonShadow, cssClasses, -} from "../../renderer/sharedStyleFields"; +} from "@/renderer/sharedStyleFields"; const description = "A container component for displaying Step components, allowing you to implement a stepped workflow."; @@ -53,8 +53,8 @@ export default { diff --git a/src/ui/src/core/auditAndFix.ts b/src/ui/src/core/auditAndFix.ts index a35276725..8760b7074 100644 --- a/src/ui/src/core/auditAndFix.ts +++ b/src/ui/src/core/auditAndFix.ts @@ -2,7 +2,7 @@ import { Component, ComponentMap, WriterComponentDefinition, -} from "../writerTypes"; +} from "@/writerTypes"; import { getComponentDefinition } from "./templateMap"; /** diff --git a/src/ui/src/core/index.ts b/src/ui/src/core/index.ts index 59c562d8b..fdda46bb0 100644 --- a/src/ui/src/core/index.ts +++ b/src/ui/src/core/index.ts @@ -8,7 +8,7 @@ import { InstancePath, MailItem, UserFunction, -} from "../writerTypes"; +} from "@/writerTypes"; import { getSupportedComponentTypes, getComponentDefinition, diff --git a/src/ui/src/core/templateMap.ts b/src/ui/src/core/templateMap.ts index dc1f2c04b..facc6330f 100644 --- a/src/ui/src/core/templateMap.ts +++ b/src/ui/src/core/templateMap.ts @@ -1,69 +1,72 @@ // Maps Writer Framework component types to renderable Vue components // content -import CoreDataframe from "../core_components/content/CoreDataframe.vue"; -import CoreHeading from "../core_components/content/CoreHeading.vue"; -import CoreIcon from "../core_components/content/CoreIcon.vue"; -import CoreImage from "../core_components/content/CoreImage.vue"; -import CoreMessage from "../core_components/content/CoreMessage.vue"; -import CoreMetric from "../core_components/content/CoreMetric.vue"; -import CorePlotlyGraph from "../core_components/content/CorePlotlyGraph.vue"; -import CoreText from "../core_components/content/CoreText.vue"; -import CoreVegaLiteChart from "../core_components/content/CoreVegaLiteChart.vue"; -import CoreVideoPlayer from "../core_components/content/CoreVideoPlayer.vue"; -import CoreLink from "../core_components/content/CoreLink.vue"; -import CoreChatbot from "../core_components/content/CoreChatbot.vue"; -import CoreTags from "../core_components/content/CoreTags.vue"; -import CoreAvatar from "../core_components/content/CoreAvatar.vue"; -import CoreAnnotatedText from "../core_components/content/CoreAnnotatedText.vue"; -import CoreJsonViewer from "../core_components/content/CoreJsonViewer.vue"; +import CoreDataframe from "../components/core/content/CoreDataframe.vue"; +import CoreHeading from "../components/core/content/CoreHeading.vue"; +import CoreIcon from "../components/core/content/CoreIcon.vue"; +import CoreImage from "../components/core/content/CoreImage.vue"; +import CoreMessage from "../components/core/content/CoreMessage.vue"; +import CoreMetric from "../components/core/content/CoreMetric.vue"; +import CorePlotlyGraph from "../components/core/content/CorePlotlyGraph.vue"; +import CoreText from "../components/core/content/CoreText.vue"; +import CoreVegaLiteChart from "../components/core/content/CoreVegaLiteChart.vue"; +import CoreVideoPlayer from "../components/core/content/CoreVideoPlayer.vue"; +import CoreLink from "../components/core/content/CoreLink.vue"; +import CoreChatbot from "../components/core/content/CoreChatbot.vue"; +import CoreTags from "../components/core/content/CoreTags.vue"; +import CoreAvatar from "../components/core/content/CoreAvatar.vue"; +import CoreAnnotatedText from "../components/core/content/CoreAnnotatedText.vue"; +import CoreJsonViewer from "../components/core/content/CoreJsonViewer.vue"; // input -import CoreCheckboxInput from "../core_components/input/CoreCheckboxInput.vue"; -import CoreColorInput from "../core_components/input/CoreColorInput.vue"; -import CoreDateInput from "../core_components/input/CoreDateInput.vue"; -import CoreDropdownInput from "../core_components/input/CoreDropdownInput.vue"; -import CoreFileInput from "../core_components/input/CoreFileInput.vue"; -import CoreMultiselectInput from "../core_components/input/CoreMultiselectInput.vue"; -import CoreNumberInput from "../core_components/input/CoreNumberInput.vue"; -import CoreRadioInput from "../core_components/input/CoreRadioInput.vue"; -import CoreSelectInput from "../core_components/input/CoreSelectInput.vue"; -import CoreSliderInput from "../core_components/input/CoreSliderInput.vue"; -import CoreTextInput from "../core_components/input/CoreTextInput.vue"; -import CoreTextareaInput from "../core_components/input/CoreTextareaInput.vue"; -import CoreTimeInput from "../core_components/input/CoreTimeInput.vue"; -import CoreRating from "../core_components/input/CoreRatingInput.vue"; -import CoreSwitchInput from "../core_components/input/CoreSwitchInput.vue"; +import CoreCheckboxInput from "../components/core/input/CoreCheckboxInput.vue"; +import CoreColorInput from "../components/core/input/CoreColorInput.vue"; +import CoreDateInput from "../components/core/input/CoreDateInput.vue"; +import CoreDropdownInput from "../components/core/input/CoreDropdownInput.vue"; +import CoreFileInput from "../components/core/input/CoreFileInput.vue"; +import CoreMultiselectInput from "../components/core/input/CoreMultiselectInput.vue"; +import CoreNumberInput from "../components/core/input/CoreNumberInput.vue"; +import CoreRadioInput from "../components/core/input/CoreRadioInput.vue"; +import CoreSelectInput from "../components/core/input/CoreSelectInput.vue"; +import CoreSliderInput from "../components/core/input/CoreSliderInput.vue"; +import CoreTextInput from "../components/core/input/CoreTextInput.vue"; +import CoreTextareaInput from "../components/core/input/CoreTextareaInput.vue"; +import CoreTimeInput from "../components/core/input/CoreTimeInput.vue"; +import CoreRating from "../components/core/input/CoreRatingInput.vue"; +import CoreSwitchInput from "../components/core/input/CoreSwitchInput.vue"; // layout -import CoreColumn from "../core_components/layout/CoreColumn.vue"; -import CoreColumns from "../core_components/layout/CoreColumns.vue"; -import CoreHeader from "../core_components/layout/CoreHeader.vue"; -import CoreHorizontalStack from "../core_components/layout/CoreHorizontalStack.vue"; -import CoreSection from "../core_components/layout/CoreSection.vue"; -import CoreSeparator from "../core_components/layout/CoreSeparator.vue"; -import CoreSidebar from "../core_components/layout/CoreSidebar.vue"; -import CoreTab from "../core_components/layout/CoreTab.vue"; -import CoreTabs from "../core_components/layout/CoreTabs.vue"; -import CoreStep from "../core_components/layout/CoreStep.vue"; -import CoreSteps from "../core_components/layout/CoreSteps.vue"; +import CoreColumn from "../components/core/layout/CoreColumn.vue"; +import CoreColumns from "../components/core/layout/CoreColumns.vue"; +import CoreHeader from "../components/core/layout/CoreHeader.vue"; +import CoreHorizontalStack from "../components/core/layout/CoreHorizontalStack.vue"; +import CoreSection from "../components/core/layout/CoreSection.vue"; +import CoreSeparator from "../components/core/layout/CoreSeparator.vue"; +import CoreSidebar from "../components/core/layout/CoreSidebar.vue"; +import CoreTab from "../components/core/layout/CoreTab.vue"; +import CoreTabs from "../components/core/layout/CoreTabs.vue"; +import CoreStep from "../components/core/layout/CoreStep.vue"; +import CoreSteps from "../components/core/layout/CoreSteps.vue"; // other -import CoreButton from "../core_components/other/CoreButton.vue"; -import CoreHtml from "../core_components/other/CoreHtml.vue"; -import CorePagination from "../core_components/other/CorePagination.vue"; -import CoreRepeater from "../core_components/other/CoreRepeater.vue"; -import CoreTimer from "../core_components/other/CoreTimer.vue"; -import CoreWebcamCapture from "../core_components/other/CoreWebcamCapture.vue"; -import CoreReuse from "../core_components/other/CoreReuse.vue"; +import CoreButton from "../components/core/other/CoreButton.vue"; +import CoreHtml from "../components/core/other/CoreHtml.vue"; +import CorePagination from "../components/core/other/CorePagination.vue"; +import CoreRepeater from "../components/core/other/CoreRepeater.vue"; +import CoreTimer from "../components/core/other/CoreTimer.vue"; +import CoreWebcamCapture from "../components/core/other/CoreWebcamCapture.vue"; +import CoreReuse from "../components/core/other/CoreReuse.vue"; // embed -import CorePDF from "../core_components/embed/CorePDF.vue"; -import CoreIFrame from "../core_components/embed/CoreIFrame.vue"; -import CoreGoogleMaps from "../core_components/embed/CoreGoogleMaps.vue"; +import CorePDF from "../components/core/embed/CorePDF.vue"; +import CoreIFrame from "../components/core/embed/CoreIFrame.vue"; +import CoreGoogleMaps from "../components/core/embed/CoreGoogleMaps.vue"; // root -import CorePage from "../core_components/root/CorePage.vue"; -import CoreRoot from "../core_components/root/CoreRoot.vue"; +import CorePage from "../components/core/root/CorePage.vue"; +import CoreRoot from "../components/core/root/CoreRoot.vue"; +import CoreMapbox from "../components/core/embed/CoreMapbox.vue"; -import CoreMapbox from "../core_components/embed/CoreMapbox.vue"; +// WORKFLOWS -import { AbstractTemplate, WriterComponentDefinition } from "../writerTypes"; +import WorkflowsNode from "../components/workflows/abstract/WorkflowsNode.vue"; + +import { AbstractTemplate, WriterComponentDefinition } from "@/writerTypes"; import { h } from "vue"; const templateMap = { @@ -122,6 +125,7 @@ const templateMap = { avatar: CoreAvatar, annotatedtext: CoreAnnotatedText, jsonviewer: CoreJsonViewer, + workflowsnode: WorkflowsNode, }; const abstractTemplateMap: Record = {}; diff --git a/src/ui/src/core/typeHierarchy.ts b/src/ui/src/core/typeHierarchy.ts index 1a687cf6e..f2065b0fa 100644 --- a/src/ui/src/core/typeHierarchy.ts +++ b/src/ui/src/core/typeHierarchy.ts @@ -1,4 +1,4 @@ -import { Component, ComponentMap } from "../writerTypes"; +import { Component, ComponentMap } from "@/writerTypes"; import { getComponentDefinition, getSupportedComponentTypes, diff --git a/src/ui/src/custom_components/BubbleMessage.vue b/src/ui/src/custom_components/BubbleMessage.vue index 0f2a5bcdb..363f7e1f3 100644 --- a/src/ui/src/custom_components/BubbleMessage.vue +++ b/src/ui/src/custom_components/BubbleMessage.vue @@ -32,8 +32,8 @@ export default { }; diff --git a/src/ui/src/renderer/ComponentRenderer.vue b/src/ui/src/renderer/ComponentRenderer.vue index 69f49dbf9..0b2d1e5a5 100644 --- a/src/ui/src/renderer/ComponentRenderer.vue +++ b/src/ui/src/renderer/ComponentRenderer.vue @@ -21,10 +21,10 @@