Skip to content

Commit

Permalink
feat(server-actions): add UI for editing server actions in studio
Browse files Browse the repository at this point in the history
GitOrigin-RevId: 9683b8caa9c7535416b01f7fb397ad9bc4c1f1c9
  • Loading branch information
IcaroG authored and actions-user committed Dec 18, 2024
1 parent 40d5b8a commit 7b08378
Show file tree
Hide file tree
Showing 10 changed files with 1,120 additions and 147 deletions.
45 changes: 44 additions & 1 deletion platform/wab/src/wab/client/components/canvas/site-ops.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ import {
Component,
ComponentArena,
ComponentDataQuery,
ComponentServerQuery,
ComponentVariantGroup,
GlobalVariantGroup,
ImageAsset,
Expand Down Expand Up @@ -1224,7 +1225,7 @@ export class SiteOps {

async removeComponentQuery(component: Component, query: ComponentDataQuery) {
const refs = findExprsInComponent(component).filter(({ expr }) =>
isQueryUsedInExpr(query, expr)
isQueryUsedInExpr(query.name, expr)
);
if (refs.length > 0) {
const viewCtx = this.studioCtx.focusedViewCtx();
Expand Down Expand Up @@ -1264,6 +1265,48 @@ export class SiteOps {
);
}

async removeComponentServerQuery(
component: Component,
query: ComponentServerQuery
) {
const refs = findExprsInComponent(component).filter(({ expr }) =>
isQueryUsedInExpr(query.name, expr)
);
if (refs.length > 0) {
const viewCtx = this.studioCtx.focusedViewCtx();
const maybeNode = refs.find((r) => r.node)?.node;
const key = mkUuid();
notification.error({
key,
message: `Cannot delete server query`,
description: (
<>
It is referenced in the current component.{" "}
{viewCtx?.component === component && maybeNode ? (
<a
onClick={() => {
viewCtx.setStudioFocusByTpl(maybeNode);
notification.close(key);
}}
>
[Go to reference]
</a>
) : null}
</>
),
});
return;
}

await this.studioCtx.changeObserved(
() => [],
({ success }) => {
this.tplMgr.removeComponentServerQuery(component, query);
return success();
}
);
}

async removeVariantGroup(component: Component, group: ComponentVariantGroup) {
const really = await this.confirmDeleteVariantGroup(group, component, {
confirm: "if-referenced",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
/** @format */

import PageSettings from "@/wab/client/components/PageSettings";
import { ComponentDataQueriesSection } from "@/wab/client/components/sidebar-tabs/component-data-queries-section";
import S from "@/wab/client/components/sidebar-tabs/ComponentTab/ComponentTab.module.scss";
import PageMetaPanel from "@/wab/client/components/sidebar-tabs/PageMetaPanel";
import { PageMinRoleSection } from "@/wab/client/components/sidebar-tabs/PageMinRoleSection";
import PageURLParametersSection from "@/wab/client/components/sidebar-tabs/PageURLParametersSection";
import VariablesSection from "@/wab/client/components/sidebar-tabs/StateManagement/VariablesSection";
import { NamedPanelHeader } from "@/wab/client/components/sidebar/sidebar-helpers";
import { ComponentDataQueriesSection } from "@/wab/client/components/sidebar-tabs/component-data-queries-section";
import { ServerQueriesSection } from "@/wab/client/components/sidebar-tabs/server-queries-section";
import { SidebarSection } from "@/wab/client/components/sidebar/SidebarSection";
import { NamedPanelHeader } from "@/wab/client/components/sidebar/sidebar-helpers";
import { TopModal } from "@/wab/client/components/studio/TopModal";
import { VariantsPanel } from "@/wab/client/components/variants/VariantsPanel";
import { Icon } from "@/wab/client/components/widgets/Icon";
Expand All @@ -17,8 +18,8 @@ import GearIcon from "@/wab/client/plasmic/plasmic_kit/PlasmicIcon__Gear";
import PageIcon from "@/wab/client/plasmic/plasmic_kit_design_system/icons/PlasmicIcon__Page";
import { StudioCtx } from "@/wab/client/studio-ctx/StudioCtx";
import { ViewCtx } from "@/wab/client/studio-ctx/view-ctx";
import { PageComponent } from "@/wab/shared/core/components";
import { PublicStyleSection } from "@/wab/shared/ApiSchema";
import { PageComponent } from "@/wab/shared/core/components";
import { canEditStyleSection } from "@/wab/shared/ui-config-utils";
import { observer } from "mobx-react";
import React from "react";
Expand Down Expand Up @@ -123,11 +124,18 @@ export const PageTab = observer(function PageTab(props: {
</>
)}
{canEdit(PublicStyleSection.DataQueries) && (
<ComponentDataQueriesSection
component={page}
viewCtx={viewCtx}
/>
<>
<ComponentDataQueriesSection
component={page}
viewCtx={viewCtx}
/>
<ServerQueriesSection
component={page}
viewCtx={viewCtx}
/>
</>
)}

{canEdit(PublicStyleSection.States) && (
<VariablesSection component={page} viewCtx={viewCtx} />
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { useBottomModalActions } from "@/wab/client/components/BottomModal";
import { DataPickerTypesSchema } from "@/wab/client/components/sidebar-tabs/DataBinding/DataPicker";
import { ServerQueryOpExprFormAndPreview } from "@/wab/client/components/sidebar-tabs/ServerQuery/ServerQueryOpPicker";
import { extractDataCtx } from "@/wab/client/state-management/interactions-meta";
import { ViewCtx } from "@/wab/client/studio-ctx/view-ctx";
import { ExprCtx } from "@/wab/shared/core/exprs";
import { EventHandlerKeyType } from "@/wab/shared/core/tpls";
import {
ComponentServerQuery,
CustomFunctionExpr,
Interaction,
TplNode,
} from "@/wab/shared/model/classes";
import { observer } from "mobx-react";
import * as React from "react";

interface ServerQueryOpExprBottomModalContentProps {
value?: CustomFunctionExpr;
onSave: (expr: CustomFunctionExpr, opExprName?: string) => unknown;
onCancel: () => unknown;
readOnly?: boolean;
readOpsOnly?: boolean;
env?: Record<string, any>;
allowedOps?: string[];
livePreview?: boolean;
exprCtx: ExprCtx;
interaction?: Interaction;
viewCtx?: ViewCtx;
tpl?: TplNode;
schema?: DataPickerTypesSchema;
parent?: ComponentServerQuery | TplNode;
eventHandlerKey?: EventHandlerKeyType;
}

/** For managing a single query modal with a known query key. */
export function useServerQueryBottomModal(queryKey: string) {
const serverQueryModals = useServerQueryBottomModals();
return {
open: (
props: {
title?: string;
} & ServerQueryOpExprBottomModalContentProps
) => {
serverQueryModals.open(queryKey, props);
},
close: () => {
serverQueryModals.close(queryKey);
},
};
}

/** For managing multiple query modals or an unknown/dynamic query. */
export function useServerQueryBottomModals() {
// const ctx = useDataSourceOpPickerContext();
const modalActions = useBottomModalActions();
return {
open: (
queryKey: string,
{
title,
...props
}: {
title?: string;
} & ServerQueryOpExprBottomModalContentProps
) => {
modalActions.open(queryKey, {
title: title || `Configure server query`,
children: <ServerQueryOpExprBottomModalContent {...props} />,
});
},
close: (queryKey: string) => {
modalActions.close(queryKey);
},
};
}

const ServerQueryOpExprBottomModalContent = observer(
function ServerQueryOpExprBottomModalContent({
value,
onSave,
onCancel,
readOnly,
readOpsOnly,
schema,
parent,
allowedOps,
livePreview,
interaction,
exprCtx,
viewCtx,
tpl,
eventHandlerKey,
...rest
}: ServerQueryOpExprBottomModalContentProps) {
const wrappedOnSave = React.useCallback(
(newExpr: CustomFunctionExpr, opExprName?: string) => {
onSave(newExpr, opExprName);
},
[onSave]
);

const env = rest.env
? rest.env
: viewCtx && tpl
? extractDataCtx(viewCtx, tpl, undefined, interaction, eventHandlerKey)
: undefined;

return (
<ServerQueryOpExprFormAndPreview
value={value}
onSave={wrappedOnSave}
onCancel={onCancel}
env={env}
schema={schema}
parent={parent}
readOnly={readOnly}
readOpsOnly={readOpsOnly}
allowedOps={allowedOps}
exprCtx={exprCtx}
interaction={interaction}
/>
);
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
@import "src/wab/styles/tokens";
@import "../../../../styles/_vars.sass";

.trashIcon {
color: $neutral-secondary;
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
width: 15px;
height: 15px;

&:hover {
color: $neutral-primary;
}
}

.stringDictKeyInput {
max-width: 34%;
}
.dataSourceExprValue {
// !important to override `.flex > *`
min-width: 100% !important;
max-width: 4vw;
text-overflow: ellipsis;
}
.container {
user-select: text;
background: #fafafa;
}

.blueIndicatorContainer {
width: 12px;
height: 12px;
display: grid;
justify-items: center;
align-items: center;
margin-right: 4px;
flex-shrink: 0;
}

.blueIndicator {
border-radius: 50%;
height: 4px;
width: 4px;
z-index: 10;
box-shadow: 0 0 0 2px white;
background: $indicator-set;
}
Loading

0 comments on commit 7b08378

Please sign in to comment.