Skip to content

Commit c9f9d90

Browse files
author
waleed
committed
cleanup checkbox in dark mode
1 parent 29fcf52 commit c9f9d90

File tree

17 files changed

+289
-265
lines changed

17 files changed

+289
-265
lines changed

apps/docs/content/docs/en/blocks/guardrails.mdx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ import { Video } from '@/components/ui/video'
1010

1111
The Guardrails block validates and protects your AI workflows by checking content against multiple validation types. Ensure data quality, prevent hallucinations, detect PII, and enforce format requirements before content moves through your workflow.
1212

13+
<div className="flex justify-center">
14+
<Image
15+
src="/static/blocks/guardrails.png"
16+
alt="Guardrails Block"
17+
width={500}
18+
height={350}
19+
className="my-6"
20+
/>
21+
</div>
22+
1323
## Overview
1424

1525
The Guardrails block enables you to:
@@ -96,6 +106,10 @@ Uses Retrieval-Augmented Generation (RAG) with LLM scoring to detect when AI-gen
96106

97107
Detects personally identifiable information using Microsoft Presidio. Supports 40+ entity types across multiple countries and languages.
98108

109+
<div className="mx-auto w-3/5 overflow-hidden rounded-lg">
110+
<Video src="guardrails.mp4" width={500} height={350} />
111+
</div>
112+
99113
**How It Works:**
100114
1. Scans content for PII entities using pattern matching and NLP
101115
2. Returns detected entities with locations and confidence scores
@@ -204,6 +218,10 @@ Additional outputs by type:
204218
</ol>
205219
</div>
206220

221+
<div className="mx-auto w-3/5 overflow-hidden rounded-lg">
222+
<Video src="guardrails-example.mp4" width={500} height={350} />
223+
</div>
224+
207225
### Validate Email Format
208226

209227
<div className="mb-4 rounded-md border p-4">
107 KB
Loading

apps/sim/app/api/guardrails/validate/route.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ export async function POST(request: NextRequest) {
2929
piiLanguage,
3030
} = body
3131

32-
// Validate required fields
3332
if (!validationType) {
3433
return NextResponse.json({
3534
success: true,
@@ -42,8 +41,6 @@ export async function POST(request: NextRequest) {
4241
})
4342
}
4443

45-
// Handle empty or missing input - but allow empty strings for JSON validation
46-
// (empty string is invalid JSON, which is a valid validation result)
4744
if (input === undefined || input === null) {
4845
return NextResponse.json({
4946
success: true,
@@ -56,7 +53,6 @@ export async function POST(request: NextRequest) {
5653
})
5754
}
5855

59-
// Validate validationType
6056
if (
6157
validationType !== 'json' &&
6258
validationType !== 'regex' &&
@@ -74,7 +70,6 @@ export async function POST(request: NextRequest) {
7470
})
7571
}
7672

77-
// For regex validation, ensure regex pattern is provided
7873
if (validationType === 'regex' && !regex) {
7974
return NextResponse.json({
8075
success: true,
@@ -87,7 +82,6 @@ export async function POST(request: NextRequest) {
8782
})
8883
}
8984

90-
// For hallucination validation, ensure model is provided
9185
if (validationType === 'hallucination' && !model) {
9286
return NextResponse.json({
9387
success: true,
@@ -100,15 +94,13 @@ export async function POST(request: NextRequest) {
10094
})
10195
}
10296

103-
// Convert input to string for validation
10497
const inputStr = convertInputToString(input)
10598

10699
logger.info(`[${requestId}] Executing validation locally`, {
107100
validationType,
108101
inputType: typeof input,
109102
})
110103

111-
// Execute validation
112104
const validationResult = await executeValidation(
113105
validationType,
114106
inputStr,
@@ -146,7 +138,6 @@ export async function POST(request: NextRequest) {
146138
})
147139
} catch (error: any) {
148140
logger.error(`[${requestId}] Guardrails validation failed`, { error })
149-
// Return validation failure instead of 500 error
150141
return NextResponse.json({
151142
success: true,
152143
output: {

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/grouped-checkbox-list.tsx

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
'use client'
22

3-
import React, { useState, useMemo } from 'react'
4-
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/hooks/use-sub-block-value'
5-
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'
3+
import { useMemo, useState } from 'react'
4+
import { Settings2 } from 'lucide-react'
65
import { Button } from '@/components/ui/button'
76
import { Checkbox } from '@/components/ui/checkbox'
8-
import { Settings2 } from 'lucide-react'
7+
import {
8+
Dialog,
9+
DialogContent,
10+
DialogHeader,
11+
DialogTitle,
12+
DialogTrigger,
13+
} from '@/components/ui/dialog'
14+
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/hooks/use-sub-block-value'
915

1016
interface GroupedCheckboxListProps {
1117
blockId: string
@@ -35,20 +41,20 @@ export function GroupedCheckboxList({
3541

3642
// Get preview value or use store value
3743
const previewValue = isPreview && subBlockValues ? subBlockValues[subBlockId]?.value : undefined
38-
const selectedValues = (isPreview ? previewValue : storeValue) as string[] || []
44+
const selectedValues = ((isPreview ? previewValue : storeValue) as string[]) || []
3945

4046
// Group options by their group property
4147
const groupedOptions = useMemo(() => {
4248
const groups: Record<string, { label: string; id: string }[]> = {}
43-
49+
4450
options.forEach((option) => {
4551
const groupName = option.group || 'Other'
4652
if (!groups[groupName]) {
4753
groups[groupName] = []
4854
}
4955
groups[groupName].push({ label: option.label, id: option.id })
5056
})
51-
57+
5258
return groups
5359
}, [options])
5460

@@ -79,41 +85,45 @@ export function GroupedCheckboxList({
7985

8086
const SelectedCountDisplay = () => {
8187
if (noneSelected) {
82-
return <span className="text-muted-foreground text-sm">None selected</span>
88+
return <span className='text-muted-foreground text-sm'>None selected</span>
8389
}
8490
if (allSelected) {
85-
return <span className="text-sm">All selected</span>
91+
return <span className='text-sm'>All selected</span>
8692
}
87-
return <span className="text-sm">{selectedValues.length} selected</span>
93+
return <span className='text-sm'>{selectedValues.length} selected</span>
8894
}
8995

9096
return (
9197
<Dialog open={open} onOpenChange={setOpen}>
9298
<DialogTrigger asChild>
93-
<Button variant="outline" className="w-full justify-between font-normal" disabled={disabled}>
94-
<span className="flex items-center gap-2">
95-
<Settings2 className="h-4 w-4" />
96-
Configure PII Types
99+
<Button
100+
variant='outline'
101+
className='h-10 w-full justify-between border-input bg-background px-3 font-normal text-sm hover:bg-accent hover:text-accent-foreground'
102+
disabled={disabled}
103+
>
104+
<span className='flex items-center gap-2 text-muted-foreground'>
105+
<Settings2 className='h-4 w-4' />
106+
<span>Configure PII Types</span>
97107
</span>
98108
<SelectedCountDisplay />
99109
</Button>
100110
</DialogTrigger>
101111
<DialogContent
102-
className="max-w-2xl max-h-[80vh] flex flex-col"
112+
className='flex max-h-[80vh] max-w-2xl flex-col'
103113
onWheel={(e) => e.stopPropagation()}
104114
>
105115
<DialogHeader>
106116
<DialogTitle>Select PII Types to Detect</DialogTitle>
107-
<p className="text-sm text-muted-foreground">
117+
<p className='text-muted-foreground text-sm'>
108118
Choose which types of personally identifiable information to detect and block.
109119
</p>
110120
</DialogHeader>
111121

112122
{/* Header with Select All and Clear */}
113-
<div className="flex items-center justify-between border-b pb-3">
114-
<div className="flex items-center gap-2">
123+
<div className='flex items-center justify-between border-b pb-3'>
124+
<div className='flex items-center gap-2'>
115125
<Checkbox
116-
id="select-all"
126+
id='select-all'
117127
checked={allSelected}
118128
onCheckedChange={(checked) => {
119129
if (checked) {
@@ -125,37 +135,40 @@ export function GroupedCheckboxList({
125135
disabled={disabled}
126136
/>
127137
<label
128-
htmlFor="select-all"
129-
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 cursor-pointer"
138+
htmlFor='select-all'
139+
className='cursor-pointer font-medium text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'
130140
>
131141
Select all entities
132142
</label>
133143
</div>
134144
<Button
135-
variant="ghost"
136-
size="sm"
145+
variant='ghost'
146+
size='sm'
137147
onClick={handleClear}
138148
disabled={disabled || noneSelected}
149+
className='w-[85px]'
139150
>
140-
Clear
151+
<span className='flex items-center gap-1'>
152+
Clear{!noneSelected && <span>({selectedValues.length})</span>}
153+
</span>
141154
</Button>
142155
</div>
143156

144157
{/* Scrollable grouped checkboxes */}
145158
<div
146-
className="flex-1 overflow-y-auto pr-4"
159+
className='flex-1 overflow-y-auto pr-4'
147160
onWheel={(e) => e.stopPropagation()}
148161
style={{ maxHeight: '60vh' }}
149162
>
150-
<div className="space-y-6">
163+
<div className='space-y-6'>
151164
{Object.entries(groupedOptions).map(([groupName, groupOptions]) => (
152165
<div key={groupName}>
153-
<h3 className="text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-3">
166+
<h3 className='mb-3 font-semibold text-muted-foreground text-xs uppercase tracking-wider'>
154167
{groupName}
155168
</h3>
156-
<div className="space-y-3">
169+
<div className='space-y-3'>
157170
{groupOptions.map((option) => (
158-
<div key={option.id} className="flex items-center gap-2">
171+
<div key={option.id} className='flex items-center gap-2'>
159172
<Checkbox
160173
id={`${subBlockId}-${option.id}`}
161174
checked={selectedValues.includes(option.id)}
@@ -164,7 +177,7 @@ export function GroupedCheckboxList({
164177
/>
165178
<label
166179
htmlFor={`${subBlockId}-${option.id}`}
167-
className="text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 cursor-pointer"
180+
className='cursor-pointer text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'
168181
>
169182
{option.label}
170183
</label>
@@ -179,4 +192,3 @@ export function GroupedCheckboxList({
179192
</Dialog>
180193
)
181194
}
182-

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ export { ConditionInput } from './condition-input'
66
export { CredentialSelector } from './credential-selector/credential-selector'
77
export { DocumentSelector } from './document-selector/document-selector'
88
export { Dropdown } from './dropdown'
9-
export { GroupedCheckboxList } from './grouped-checkbox-list'
109
export { EvalInput } from './eval-input'
1110
export { FileSelectorInput } from './file-selector/file-selector-input'
1211
export { FileUpload } from './file-upload'
1312
export { FolderSelectorInput } from './folder-selector/components/folder-selector-input'
13+
export { GroupedCheckboxList } from './grouped-checkbox-list'
1414
export { InputMapping } from './input-mapping/input-mapping'
1515
export { KnowledgeBaseSelector } from './knowledge-base-selector/knowledge-base-selector'
1616
export { LongInput } from './long-input'

0 commit comments

Comments
 (0)