diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index bb40b324ef..b7b49a7618 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -32,7 +32,7 @@ services: - APPLICATION_NAME=unstract-backend labels: - traefik.enable=true - - traefik.http.routers.backend.rule=Host(`frontend.unstract.localhost`) && (PathPrefix(`/api/v1`) || PathPrefix(`/deployment`)) + - traefik.http.routers.backend.rule=Host(`frontend.unstract.localhost`) && (PathPrefix(`/api/v1`) || PathPrefix(`/deployment`) || PathPrefix(`/public`)) - traefik.http.services.backend.loadbalancer.server.port=8000 extra_hosts: # "host-gateway" is a special string that translates to host docker0 i/f IP. @@ -134,7 +134,7 @@ services: - ENVIRONMENT=development labels: - traefik.enable=true - - traefik.http.routers.frontend.rule=Host(`frontend.unstract.localhost`) && !PathPrefix(`/api/v1`) && !PathPrefix(`/deployment`) + - traefik.http.routers.frontend.rule=Host(`frontend.unstract.localhost`) && !PathPrefix(`/api/v1`) && !PathPrefix(`/deployment`) && !PathPrefix(`/public`) - traefik.http.services.frontend.loadbalancer.server.port=80 platform-service: diff --git a/docker/sample.proxy_overrides.yaml b/docker/sample.proxy_overrides.yaml index f73266a18e..3167dafa96 100644 --- a/docker/sample.proxy_overrides.yaml +++ b/docker/sample.proxy_overrides.yaml @@ -5,7 +5,7 @@ http: rule: Host(`frontend.unstract.localhost`) backend: service: backend - rule: Host(`frontend.unstract.localhost`) && (PathPrefix(`/api/v1`) || PathPrefix(`/deployment`)) + rule: Host(`frontend.unstract.localhost`) && (PathPrefix(`/api/v1`) || PathPrefix(`/deployment`) || PathPrefix(`/public`)) services: frontend: diff --git a/frontend/src/components/custom-tools/combined-output/JsonView.jsx b/frontend/src/components/custom-tools/combined-output/JsonView.jsx index 34a733598a..36e11c4648 100644 --- a/frontend/src/components/custom-tools/combined-output/JsonView.jsx +++ b/frontend/src/components/custom-tools/combined-output/JsonView.jsx @@ -2,8 +2,9 @@ import { Tabs } from "antd"; import TabPane from "antd/es/tabs/TabPane"; import Prism from "prismjs"; import PropTypes from "prop-types"; -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; +import { useCustomToolStore } from "../../../store/custom-tool-store"; import { JsonViewBody } from "./JsonViewBody"; let EnrichedOutputToggle; @@ -27,17 +28,31 @@ function JsonView({ isSinglePass, isLoading, }) { - const [activeView, setActiveView] = useState("Raw"); + // Read-only viewers default to the enriched value. + const isPublicSource = useCustomToolStore((s) => s.isPublicSource); + const [activeView, setActiveView] = useState( + isPublicSource ? "Enriched" : "Raw", + ); + const didInitTab = useRef(false); useEffect(() => { Prism.highlightAll(); }, [combinedOutput, enrichedOutput, activeView]); useEffect(() => { - if (!enrichedOutput || Object.keys(enrichedOutput).length === 0) { + const hasEnriched = + enrichedOutput && Object.keys(enrichedOutput).length > 0; + if (!hasEnriched) { setActiveView("Raw"); + didInitTab.current = false; + return; + } + // Public viewer default fires once so a manual Raw toggle isn't stomped on re-renders. + if (isPublicSource && !didInitTab.current) { + setActiveView("Enriched"); + didInitTab.current = true; } - }, [enrichedOutput]); + }, [enrichedOutput, isPublicSource]); const displayOutput = activeView === "Enriched" && diff --git a/frontend/src/hooks/useAxiosPrivate.js b/frontend/src/hooks/useAxiosPrivate.js index 9d86b2f653..7abc500038 100644 --- a/frontend/src/hooks/useAxiosPrivate.js +++ b/frontend/src/hooks/useAxiosPrivate.js @@ -14,8 +14,20 @@ function useAxiosPrivate() { }, async (error) => { if (error?.response?.status === 401) { - // TODO: Implement Session Expired Modal - logout(); + // Skip logout on routes that intentionally render without a session. + const onPublicShare = + typeof globalThis !== "undefined" && + globalThis.location?.pathname.startsWith("/promptStudio/share/"); + if (onPublicShare) { + // Keep a breadcrumb so a stray authenticated probe doesn't go silent. + console.warn("[useAxiosPrivate] Suppressed 401 on public share", { + url: error?.config?.url, + path: globalThis.location?.pathname, + }); + } else { + // TODO: Implement Session Expired Modal + logout(); + } } return Promise.reject(error); },