diff --git a/apps/builder/app/builder/features/settings-panel/resource-panel.tsx b/apps/builder/app/builder/features/settings-panel/resource-panel.tsx index dbbf64c29bd1..a902ea12b76d 100644 --- a/apps/builder/app/builder/features/settings-panel/resource-panel.tsx +++ b/apps/builder/app/builder/features/settings-panel/resource-panel.tsx @@ -66,7 +66,10 @@ import { type InstancePath, } from "~/shared/awareness"; import { updateWebstudioData } from "~/shared/instance-utils"; -import { rebindTreeVariablesMutable } from "~/shared/data-variables"; +import { + computeExpression, + rebindTreeVariablesMutable, +} from "~/shared/data-variables"; import { parseCurl, type CurlRequest } from "./curl"; export const parseResource = ({ @@ -478,6 +481,40 @@ export const Headers = ({ ); }; +const CacheMaxAge = ({ + value, + onChange, +}: { + value: undefined | string; + onChange: (newValue: string) => void; +}) => { + return ( + + + + S + + } + value={value ?? ""} + onChange={(event) => onChange(event.target.value)} + /> + {value && ( + <> + + + + )} + + ); +}; + export const getResourceScopeForInstance = ({ page, instanceKey, @@ -602,9 +639,11 @@ type PanelApi = { save: (formData: FormData) => void; }; +type BodyType = undefined | "text" | "json"; + const validateBody = ( value: string, - contentType: unknown, + bodyType: BodyType, scope: Record ) => { // skip empty expressions @@ -612,7 +651,7 @@ const validateBody = ( return ""; } const evaluatedValue = evaluateExpressionWithinScope(value, scope); - if (contentType === "application/json") { + if (bodyType === "json") { return typeof evaluatedValue === "object" && evaluatedValue !== null ? "" : "Expected valid JSON object in body"; @@ -621,18 +660,27 @@ const validateBody = ( } }; +const toMime = (bodyType: BodyType) => { + if (bodyType === "json") { + return "application/json"; + } + if (bodyType === "text") { + return "text/plain"; + } +}; + const BodyField = ({ scope, aliases, - contentType, + bodyType, value, onChange, }: { aliases: Map; scope: Record; - contentType: unknown; + bodyType: BodyType; value: string; - onChange: (value: string) => void; + onChange: (value: string, bodyType: BodyType) => void; }) => { const [isBodyLiteral, setIsBodyLiteral] = useState( () => value === "" || isLiteralExpression(value) @@ -640,13 +688,41 @@ const BodyField = ({ const [bodyError, setBodyError] = useState(""); const bodyRef = useRef(null); useEffect(() => { - bodyRef.current?.setCustomValidity(validateBody(value, contentType, scope)); + bodyRef.current?.setCustomValidity(validateBody(value, bodyType, scope)); setBodyError(""); - }, [value, contentType, scope]); + }, [value, bodyType, scope]); + const updateBody = (newBody: string) => { + const evaluatedValue = evaluateExpressionWithinScope(newBody, scope); + // automatically add Content-Type: application/json header + // when value is object + const isBodyObject = + typeof evaluatedValue === "object" && evaluatedValue !== null; + onChange(newBody, isBodyObject ? "json" : bodyType); + }; return ( + + placeholder="Type" + value={bodyType ?? ""} + options={["text", "json"]} + onChange={(newBodyType) => { + if (newBodyType) { + onChange(value, newBodyType); + } + }} + /> + {bodyType && ( + <> + + + + )}