diff --git a/plugins/nemo-agents/examples/email-phishing-analyzer/src/nat_email_phishing_analyzer/data/smaller_test.csv b/plugins/nemo-agents/examples/email-phishing-analyzer/src/nat_email_phishing_analyzer/data/smaller_test.csv index fc31b29974..f23fc8a0eb 100644 --- a/plugins/nemo-agents/examples/email-phishing-analyzer/src/nat_email_phishing_analyzer/data/smaller_test.csv +++ b/plugins/nemo-agents/examples/email-phishing-analyzer/src/nat_email_phishing_analyzer/data/smaller_test.csv @@ -15,11 +15,11 @@ http://invoice-example.com/view?invoice=12345 If you have any questions, feel free to contact us. Best regards, Customer Service",2023-07-01 09:30:45,accounts@shop-example.com,"{'money': {'label': 'Money', 'id': 0, 'score': 0.9997}, 'banking': {'label': 'Personal', 'id': 1, 'score': 0.9998}, 'crypto': {'label': 'NonCrypto', 'id': 1, 'score': 0.9994}}",phishing,money,pending -Benign: Project Meeting Reminder,"Hi Team, +Project Meeting Reminder,"Hi Team, Just wanted to remind you about our project update meeting on Friday at 2pm. Please let me know if you can attend. Thanks! -Bob",2023-08-10 15:30:00,bob@example.com,"{'money': {'label': 'NonMoney', 'id': 1, 'score': 0.9995}, 'banking': {'label': 'NonPersonal', 'id': 1, 'score': 0.9995}, 'crypto': {'label': 'NonCrypto', 'id': 1, 'score': 0.9994}}",benign,meeting,trusted -Benign: Invoice Follow-up,"Hi John, +Invoice Follow-up,"Hi John, Please find the invoice #1234 attached for your recent purchase. Let me know if you have any questions. Best regards, Alice",2023-09-01 09:15:22,alice@company.com,"{'money': {'label': 'Money', 'id': 0, 'score': 0.9996}, 'banking': {'label': 'Personal', 'id': 1, 'score': 0.9996}, 'crypto': {'label': 'NonCrypto', 'id': 1, 'score': 0.9993}}",benign,finance,trusted diff --git a/plugins/nemo-agents/examples/email-phishing-analyzer/src/nat_email_phishing_analyzer/data/smaller_test_seed.csv b/plugins/nemo-agents/examples/email-phishing-analyzer/src/nat_email_phishing_analyzer/data/smaller_test_seed.csv new file mode 100644 index 0000000000..d437783c61 --- /dev/null +++ b/plugins/nemo-agents/examples/email-phishing-analyzer/src/nat_email_phishing_analyzer/data/smaller_test_seed.csv @@ -0,0 +1,6 @@ +source,intents,sender +gift,"{'money': {'label': 'Money', 'id': 0, 'score': 0.9998}, 'banking': {'label': 'Personal', 'id': 1, 'score': 0.9997}, 'crypto': {'label': 'NonCrypto', 'id': 1, 'score': 0.9996}}",prize@example.com +password,"{'money': {'label': 'Money', 'id': 0, 'score': 0.9999}, 'banking': {'label': 'Personal', 'id': 1, 'score': 0.9999}, 'crypto': {'label': 'NonCrypto', 'id': 1, 'score': 0.9995}}",security-alerts@bank.com +money,"{'money': {'label': 'Money', 'id': 0, 'score': 0.9997}, 'banking': {'label': 'Personal', 'id': 1, 'score': 0.9998}, 'crypto': {'label': 'NonCrypto', 'id': 1, 'score': 0.9994}}",accounts@shop-example.com +meeting,"{'money': {'label': 'NonMoney', 'id': 1, 'score': 0.9995}, 'banking': {'label': 'NonPersonal', 'id': 1, 'score': 0.9995}, 'crypto': {'label': 'NonCrypto', 'id': 1, 'score': 0.9994}}",bob@example.com +finance,"{'money': {'label': 'Money', 'id': 0, 'score': 0.9996}, 'banking': {'label': 'Personal', 'id': 1, 'score': 0.9996}, 'crypto': {'label': 'NonCrypto', 'id': 1, 'score': 0.9993}}",alice@company.com diff --git a/web/packages/studio/src/components/ColumnConfigPanel/SeedDatasetConfig.tsx b/web/packages/studio/src/components/ColumnConfigPanel/SeedDatasetConfig.tsx index b87e34df00..258ff96f84 100644 --- a/web/packages/studio/src/components/ColumnConfigPanel/SeedDatasetConfig.tsx +++ b/web/packages/studio/src/components/ColumnConfigPanel/SeedDatasetConfig.tsx @@ -5,8 +5,9 @@ import { FilesetSearchableSelect } from '@nemo/common/src/components/FilesetSear import { ControlledSelect } from '@nemo/common/src/components/form/ControlledSelect'; import { getPartsFromReference } from '@nemo/common/src/namedEntity'; import { useFilesListFilesetFiles } from '@nemo/sdk/generated/platform/api'; -import { Flex, FormField, Tag, Text } from '@nvidia/foundations-react-core'; +import { Button, Flex, FormField, Tag, Text } from '@nvidia/foundations-react-core'; import { useDatasetFileContent } from '@studio/api/datasets/useDatasetFileContent'; +import { FilesetFilePreviewPanel } from '@studio/components/FilesetFilePreviewPanel'; import { useWorkspaceFromPath } from '@studio/hooks/useWorkspaceFromPath'; import { SAMPLING_STRATEGY_OPTIONS, @@ -17,7 +18,8 @@ import { } from '@studio/routes/DataDesignerJobBuildRoute/columns'; import type { JobBuilderFormValues } from '@studio/routes/DataDesignerJobBuildRoute/useJobBuilder'; import { getContentColumns, getFileExtension } from '@studio/util/files'; -import { type FC, useEffect, useMemo, useRef } from 'react'; +import { Eye } from 'lucide-react'; +import { type FC, useEffect, useMemo, useRef, useState } from 'react'; import { useFormContext, useWatch } from 'react-hook-form'; export interface SeedDatasetConfigProps { @@ -51,12 +53,15 @@ export const SeedDatasetConfig: FC = ({ columnIndex }) = name: availableColumnsPath, }); + const [isPreviewOpen, setIsPreviewOpen] = useState(false); + const previousFilesetRef = useRef(filesetRef); useEffect(() => { if (previousFilesetRef.current === filesetRef) return; previousFilesetRef.current = filesetRef; setValue(filePathPath, ''); setValue(availableColumnsPath, ''); + setIsPreviewOpen(false); }, [availableColumnsPath, filePathPath, filesetRef, setValue]); const { workspace: filesetWorkspace, name: filesetName } = getPartsFromReference(filesetRef); @@ -119,11 +124,29 @@ export const SeedDatasetConfig: FC = ({ columnIndex }) = items={fileItems} useControllerProps={{ name: filePathPath }} formFieldProps={{ - slotLabel: 'File', + slotLabel: ( + + File + + + ), required: true, slotInfo: 'The file within the fileset to read rows from.', }} - onChange={() => setValue(availableColumnsPath, '')} + onChange={() => { + setValue(availableColumnsPath, ''); + setIsPreviewOpen(false); + }} placeholder={ !filesetRef ? 'Select a fileset first' @@ -172,6 +195,15 @@ export const SeedDatasetConfig: FC = ({ columnIndex }) = }} placeholder="Ordered" /> + + setIsPreviewOpen(false)} + onOutsideClick={() => setIsPreviewOpen(false)} + workspace={filesetWorkspace} + filesetName={filesetName} + filePath={filePath} + /> ); }; diff --git a/web/packages/studio/src/routes/DataDesignerJobBuildRoute/SchemaList.tsx b/web/packages/studio/src/routes/DataDesignerJobBuildRoute/SchemaList.tsx index 39ac9661b5..a97ef742de 100644 --- a/web/packages/studio/src/routes/DataDesignerJobBuildRoute/SchemaList.tsx +++ b/web/packages/studio/src/routes/DataDesignerJobBuildRoute/SchemaList.tsx @@ -3,6 +3,7 @@ import { Flex, Stack, Text } from '@nvidia/foundations-react-core'; import { + buildNameMaps, getColumnReferences, topologicalSortColumns, } from '@studio/routes/DataDesignerJobBuildRoute/columns'; @@ -28,7 +29,7 @@ export const SchemaList: FC = ({ selectedId, onSelect, onDelete const columnRecord = useWatch({ control, name: 'columns' }); const columns = useMemo(() => topologicalSortColumns(columnRecord), [columnRecord]); const referencesById = useMemo(() => { - const knownNames = new Set(columns.map((column) => column.name).filter(Boolean)); + const { knownNames } = buildNameMaps(columns); return new Map(columns.map((column) => [column.id, getColumnReferences(column, knownNames)])); }, [columns]); diff --git a/web/packages/studio/src/routes/DataDesignerJobBuildRoute/columns.ts b/web/packages/studio/src/routes/DataDesignerJobBuildRoute/columns.ts index 5c486b592f..0246fd31df 100644 --- a/web/packages/studio/src/routes/DataDesignerJobBuildRoute/columns.ts +++ b/web/packages/studio/src/routes/DataDesignerJobBuildRoute/columns.ts @@ -736,7 +736,7 @@ export const getColumnReferences = (column: BuilderColumn, knownNames: Set; idByName: Map } => { const knownNames = new Set(columns.map((column) => column.name).filter(Boolean));