Skip to content

Commit 51d3d27

Browse files
authored
Portal policies: SUI setup forms fixes and improvements (Stirling-Tools#6927)
## What this does Reworks the portal's policy setup screens so a policy reads as **its own settings** rather than a list of tools you wire together, and rebuilds the forms on the shared design system so they match the rest of the portal. ## Why Setup showed one card per underlying tool (tool name + a toggle), which exposed the "a policy is a pipeline of tools" plumbing. A policy should read in terms of what it does to a document, not which tools run under the hood. ## Changes - **Setup reads as policy settings.** The per-tool cards are now a plain-language list of what the policy does — "Redact sensitive information", "Strip active content", "Apply a watermark", and so on — each with a short description and a toggle, with its options appearing inline when turned on. - **Consistent design system.** The setup and edit forms use the shared components instead of one-off styling. - **Simpler setup.** Removed two sections that aren't part of what ships here: Document Types (scope-by-type) and Retries. - **Watermarks are text-only.** A policy watermark is a text stamp, so the image option and the type picker are hidden. - **The editor always shows as a source** (it used to disappear when no other sources were connected), and the source tiles now lay out correctly. - **Clearer upsell copy.** Locked policies read **"Upgrade to Enterprise"** instead of "Coming soon". ## Scope UI only — no backend changes. Keeping a policy's settings in sync between the portal and the editor is a known, separate issue and is **not** part of this PR. ## Testing Prettier, ESLint, typecheck (proprietary + saas), and the unused-translation guard all pass. Setup screens verified in Storybook.
1 parent ccfd22b commit 51d3d27

10 files changed

Lines changed: 290 additions & 237 deletions

File tree

frontend/editor/public/locales/en-US/translation.toml

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7404,7 +7404,7 @@ subtitle = "Standing automations that enforce a tool pipeline on every document.
74047404
title = "Policies"
74057405

74067406
[portal.policies.card]
7407-
comingSoon = "Coming soon"
7407+
comingSoon = "Upgrade to Enterprise"
74087408
notSetUp = "Not set up"
74097409

74107410
[portal.policies.categories.compliance]
@@ -7566,14 +7566,29 @@ continue = "Continue"
75667566
enablePolicy = "Enable policy"
75677567
saveChanges = "Save changes"
75687568

7569-
[portal.policies.wizard.docTypes]
7570-
allDescription = "Set up an Ingestion (classification) policy to narrow this to specific document types."
7571-
allTitle = "All document types"
7572-
clear = "Clear"
7573-
heading = "Document types"
7574-
narrow = "Narrow"
7575-
selected_one = "{{count}} selected"
7576-
selected_other = "{{count}} selected"
7569+
[portal.policies.wizard.capability.compress]
7570+
desc = "Compresses the document to a smaller file size."
7571+
label = "Reduce file size"
7572+
7573+
[portal.policies.wizard.capability.flatten]
7574+
desc = "Merges form fields and annotations into the page so they can't be edited."
7575+
label = "Flatten the document"
7576+
7577+
[portal.policies.wizard.capability.ocr]
7578+
desc = "Runs OCR so scanned pages become selectable, searchable text."
7579+
label = "Make text searchable"
7580+
7581+
[portal.policies.wizard.capability.redact]
7582+
desc = "Finds and blacks out sensitive details — like Social Security and card numbers — so they can't be read."
7583+
label = "Redact sensitive information"
7584+
7585+
[portal.policies.wizard.capability.sanitize]
7586+
desc = "Removes hidden JavaScript so nothing can run automatically when the document is opened."
7587+
label = "Strip active content"
7588+
7589+
[portal.policies.wizard.capability.watermark]
7590+
desc = "Stamps a visible mark (e.g. “Confidential”) across every page."
7591+
label = "Apply a watermark"
75777592

75787593
[portal.policies.wizard.errors]
75797594
noTools = "Enable at least one tool in the workflow first."
@@ -7594,11 +7609,6 @@ label = "Output as"
75947609
newFile = "New file"
75957610
newVersion = "New version"
75967611

7597-
[portal.policies.wizard.output.retries]
7598-
delayLabel = "Retry delay (min)"
7599-
heading = "Retries"
7600-
maxLabel = "Max retries"
7601-
76027612
[portal.policies.wizard.output.runOn]
76037613
export = "Export"
76047614
helper = "When the policy fires: on upload, or before export."
@@ -7609,22 +7619,20 @@ upload = "Upload"
76097619
heading = "Settings"
76107620

76117621
[portal.policies.wizard.sources]
7612-
emptyDescription = "Connect a source on the Sources page first, then attach it to a policy here."
7613-
emptyTitle = "No sources available"
76147622
heading = "Sources"
76157623
loading = "Loading sources…"
76167624

76177625
[portal.policies.wizard.tabs]
76187626
ariaLabel = "Setup steps"
76197627
settings = "Settings"
7620-
workflow = "Workflow"
7628+
workflow = "Actions"
76217629

76227630
[portal.policies.wizard.title]
76237631
edit = "Edit {{category}} policy"
76247632
setUp = "Set up {{category}} policy"
76257633

76267634
[portal.policies.wizard.workflow]
7627-
description = "The sequence of tools this policy runs on each document. Each tool is a Stirling endpoint; toggle the ones this policy should enforce."
7635+
description = "Choose what this policy does to every document it processes."
76287636

76297637
[portal.policySummary]
76307638
activeSummary = "{{active}} / {{total}} active"
@@ -7633,7 +7641,7 @@ subtitle = "Standing automations every document passes through, regardless of wh
76337641
title = "What runs on your PDFs"
76347642

76357643
[portal.policySummary.action]
7636-
comingSoon = "Coming soon"
7644+
comingSoon = "Upgrade to Enterprise"
76377645
configure = "Configure"
76387646
setUp = "Set up"
76397647

frontend/editor/src/core/components/tools/addWatermark/AddWatermarkSingleStepSettings.tsx

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,33 @@ interface AddWatermarkSingleStepSettingsProps {
2323
disabled?: boolean;
2424
/** When false, hide the "Flatten PDF pages to images" option (e.g. in policies). */
2525
showFlatten?: boolean;
26+
/** When true, lock to text watermarks: hide the type selector and image option (e.g. in policies). */
27+
textOnly?: boolean;
2628
}
2729

2830
const AddWatermarkSingleStepSettings = ({
2931
parameters,
3032
onParameterChange,
3133
disabled = false,
3234
showFlatten = true,
35+
textOnly = false,
3336
}: AddWatermarkSingleStepSettingsProps) => {
37+
const isText = textOnly || parameters.watermarkType === "text";
38+
const isImage = !textOnly && parameters.watermarkType === "image";
3439
return (
3540
<Stack gap="lg">
36-
{/* Watermark Type Selection */}
37-
<WatermarkTypeSettings
38-
watermarkType={parameters.watermarkType}
39-
onWatermarkTypeChange={(type) =>
40-
onParameterChange("watermarkType", type)
41-
}
42-
disabled={disabled}
43-
/>
41+
{/* Watermark type selection — hidden when locked to text. */}
42+
{!textOnly && (
43+
<WatermarkTypeSettings
44+
watermarkType={parameters.watermarkType}
45+
onWatermarkTypeChange={(type) =>
46+
onParameterChange("watermarkType", type)
47+
}
48+
disabled={disabled}
49+
/>
50+
)}
4451

45-
{/* Conditional settings based on watermark type */}
46-
{parameters.watermarkType === "text" && (
52+
{isText && (
4753
<>
4854
<WatermarkWording
4955
parameters={parameters}
@@ -58,7 +64,7 @@ const AddWatermarkSingleStepSettings = ({
5864
</>
5965
)}
6066

61-
{parameters.watermarkType === "image" && (
67+
{isImage && (
6268
<WatermarkImageFile
6369
parameters={parameters}
6470
onParameterChange={onParameterChange}
@@ -67,7 +73,7 @@ const AddWatermarkSingleStepSettings = ({
6773
)}
6874

6975
{/* Formatting settings for both text and image */}
70-
{parameters.watermarkType && (
76+
{(textOnly || parameters.watermarkType) && (
7177
<WatermarkFormatting
7278
parameters={parameters}
7379
onParameterChange={onParameterChange}

frontend/editor/src/portal/PortalApp.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { PortalAuthBoundary } from "@portal/auth/PortalAuthBoundary";
33
import { ThemeProvider, useTheme } from "@portal/contexts/ThemeContext";
44
import { SuiProvider } from "@portal/theme/SuiProvider";
55
import { PortalProviders } from "@portal/PortalProviders";
6+
import { ToolRegistryProvider } from "@app/contexts/ToolRegistryProvider";
67
// Reset + typography, scoped to .portal-scope below.
78
import "@portal/theme/base.css";
89

@@ -32,9 +33,13 @@ export function PortalApp() {
3233
<ThemedSuiProvider>
3334
{/* Scopes base.css to the portal so it doesn't restyle the host editor. */}
3435
<div className="portal-scope">
35-
<PortalAuthBoundary>
36-
<PortalProviders />
37-
</PortalAuthBoundary>
36+
{/* Tool registry is read by portal views (e.g. the policy setup
37+
wizard); mount it above the per-flavor provider split. */}
38+
<ToolRegistryProvider>
39+
<PortalAuthBoundary>
40+
<PortalProviders />
41+
</PortalAuthBoundary>
42+
</ToolRegistryProvider>
3843
</div>
3944
</ThemedSuiProvider>
4045
</ThemeProvider>

frontend/editor/src/portal/components/policies/PolicySetupWizard.stories.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Meta, StoryObj } from "@storybook/react-vite";
2+
import { ToolRegistryProvider } from "@app/contexts/ToolRegistryProvider";
23
import {
34
POLICY_CATEGORIES,
45
POLICY_CONFIG,
@@ -12,6 +13,15 @@ const meta: Meta<typeof PolicySetupWizard> = {
1213
title: "Portal/Policies/PolicySetupWizard",
1314
component: PolicySetupWizard,
1415
parameters: { layout: "fullscreen" },
16+
// The wizard reads the tool registry (for capability fallback names/icons),
17+
// so stories must supply the provider the app mounts in PortalApp.
18+
decorators: [
19+
(Story) => (
20+
<ToolRegistryProvider>
21+
<Story />
22+
</ToolRegistryProvider>
23+
),
24+
],
1525
args: {
1626
onClose: () => {},
1727
onSubmit: async () => {},

0 commit comments

Comments
 (0)