@burdenoff/microfe-cosmicintersection 2026.704.1 → 2026.704.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cosmicintersection/CosmicIntersectionRoutes.js +45 -25
- package/dist/cosmicintersection/CosmicIntersectionRoutes.js.map +1 -1
- package/dist/cosmicintersection/api/cosmicApi.js +137 -66
- package/dist/cosmicintersection/api/cosmicApi.js.map +1 -1
- package/dist/cosmicintersection/components/ActivityFeedPanel.js +68 -0
- package/dist/cosmicintersection/components/ActivityFeedPanel.js.map +1 -0
- package/dist/cosmicintersection/components/DiscussionPanel.js +57 -0
- package/dist/cosmicintersection/components/DiscussionPanel.js.map +1 -0
- package/dist/cosmicintersection/components/FacetPanel.js +66 -0
- package/dist/cosmicintersection/components/FacetPanel.js.map +1 -0
- package/dist/cosmicintersection/components/LineageGraph.js +388 -0
- package/dist/cosmicintersection/components/LineageGraph.js.map +1 -0
- package/dist/cosmicintersection/components/ResultsChart.js +329 -0
- package/dist/cosmicintersection/components/ResultsChart.js.map +1 -0
- package/dist/cosmicintersection/components/StepDAG.js +104 -0
- package/dist/cosmicintersection/components/StepDAG.js.map +1 -0
- package/dist/cosmicintersection/components/index.js +5 -3
- package/dist/cosmicintersection/pages/access/AccessPage.js +220 -161
- package/dist/cosmicintersection/pages/access/AccessPage.js.map +1 -1
- package/dist/cosmicintersection/pages/analyses/AnalysesPage.js +332 -172
- package/dist/cosmicintersection/pages/analyses/AnalysesPage.js.map +1 -1
- package/dist/cosmicintersection/pages/collections/CollectionDetailPage.js +167 -109
- package/dist/cosmicintersection/pages/collections/CollectionDetailPage.js.map +1 -1
- package/dist/cosmicintersection/pages/collections/CollectionFormPage.js +87 -61
- package/dist/cosmicintersection/pages/collections/CollectionFormPage.js.map +1 -1
- package/dist/cosmicintersection/pages/collections/CollectionsPage.js +51 -42
- package/dist/cosmicintersection/pages/collections/CollectionsPage.js.map +1 -1
- package/dist/cosmicintersection/pages/dashboard/DashboardPage.js +31 -18
- package/dist/cosmicintersection/pages/dashboard/DashboardPage.js.map +1 -1
- package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.js +330 -184
- package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.js.map +1 -1
- package/dist/cosmicintersection/pages/datasets/DatasetFormPage.js +7 -7
- package/dist/cosmicintersection/pages/datasets/DatasetsPage.js +321 -163
- package/dist/cosmicintersection/pages/datasets/DatasetsPage.js.map +1 -1
- package/dist/cosmicintersection/pages/discovery/DiscoveryPage.js +358 -0
- package/dist/cosmicintersection/pages/discovery/DiscoveryPage.js.map +1 -0
- package/dist/cosmicintersection/pages/lineage/LineagePage.js +171 -0
- package/dist/cosmicintersection/pages/lineage/LineagePage.js.map +1 -0
- package/dist/cosmicintersection/pages/notebooks/NotebookDetailPage.js +339 -260
- package/dist/cosmicintersection/pages/notebooks/NotebookDetailPage.js.map +1 -1
- package/dist/cosmicintersection/pages/notebooks/NotebooksPage.js +143 -82
- package/dist/cosmicintersection/pages/notebooks/NotebooksPage.js.map +1 -1
- package/dist/cosmicintersection/pages/pipelines/PipelineDetailPage.js +286 -142
- package/dist/cosmicintersection/pages/pipelines/PipelineDetailPage.js.map +1 -1
- package/dist/cosmicintersection/pages/pipelines/PipelineFormPage.js +305 -103
- package/dist/cosmicintersection/pages/pipelines/PipelineFormPage.js.map +1 -1
- package/dist/cosmicintersection/pages/pipelines/PipelinesPage.js +183 -79
- package/dist/cosmicintersection/pages/pipelines/PipelinesPage.js.map +1 -1
- package/dist/cosmicintersection/pages/releases/ReleasesPage.js +346 -204
- package/dist/cosmicintersection/pages/releases/ReleasesPage.js.map +1 -1
- package/dist/cosmicintersection/pages/runs/RunDetailPage.js +184 -136
- package/dist/cosmicintersection/pages/runs/RunDetailPage.js.map +1 -1
- package/dist/cosmicintersection/pages/runs/RunsPage.js +182 -120
- package/dist/cosmicintersection/pages/runs/RunsPage.js.map +1 -1
- package/dist/cosmicintersection/pages/sources/SourceDetailPage.js +234 -0
- package/dist/cosmicintersection/pages/sources/SourceDetailPage.js.map +1 -0
- package/dist/cosmicintersection/pages/sources/SourcesPage.js +250 -133
- package/dist/cosmicintersection/pages/sources/SourcesPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatasetDetailPage.js","names":[],"sources":["../../../../src/cosmicintersection/pages/datasets/DatasetDetailPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n Boxes,\n Columns3,\n Database,\n Download,\n MessagesSquare,\n Pencil,\n Plus,\n Radar,\n} from 'lucide-react';\nimport {\n Badge,\n Button,\n Checkbox,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n useCosAddSchemaFieldMutation,\n useCosArchiveDatasetMutation,\n useCosDatasetQuery,\n useCosPublishDatasetMutation,\n useCosUpdateDatasetMutation,\n type CosFieldType,\n} from '../../api/cosmicApi';\nimport {\n ActionMenu,\n EmptyState,\n EntityTagsField,\n ErrorState,\n LoadingState,\n PageLayout,\n SafeLink,\n StatusBadge,\n formatEnumLabel,\n useFileDownloadUrl,\n} from '../../components';\nimport { useCosmicIntersection } from '../../context/CosmicIntersectionContext';\nimport { notify } from '../../lib/toast';\n\nconst FIELD_TYPES: CosFieldType[] = [\n 'STRING',\n 'INTEGER',\n 'FLOAT',\n 'BOOLEAN',\n 'TIMESTAMP',\n 'COORDINATE',\n 'SPECTRUM',\n 'GEOMETRY',\n 'IMAGE_REF',\n 'JSON',\n];\n\nfunction formatBytes(raw: string | null | undefined): string {\n if (!raw) {\n return '—';\n }\n const bytes = Number(raw);\n if (!Number.isFinite(bytes) || bytes <= 0) {\n return '—';\n }\n const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];\n let value = bytes;\n let unit = 0;\n while (value >= 1024 && unit < units.length - 1) {\n value /= 1024;\n unit += 1;\n }\n return `${value >= 10 || unit === 0 ? Math.round(value) : value.toFixed(1)} ${units[unit]}`;\n}\n\nfunction formatDateTime(raw: string | null | undefined): string {\n if (!raw) {\n return '—';\n }\n const date = new Date(raw);\n return Number.isNaN(date.getTime()) ? '—' : date.toLocaleString();\n}\n\nfunction MetaTile({ label, value }: { label: string; value: React.ReactNode }) {\n return (\n <div className=\"rounded-card border border-border-default bg-bg-elevated p-4\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">{label}</p>\n <div className=\"mt-1 text-sm text-text-primary\">{value}</div>\n </div>\n );\n}\n\nexport default function DatasetDetailPage() {\n const { id = '' } = useParams<{ id: string }>();\n const { navigate } = useCosmicIntersection();\n\n const { data, loading, error, refetch } = useCosDatasetQuery(id);\n const dataset = data?.cosDataset ?? null;\n\n const download = useFileDownloadUrl(dataset?.file?.id);\n const downloadUrl = download.data?.getFileDownloadUrl ?? null;\n\n const [publishDataset, { loading: publishing }] = useCosPublishDatasetMutation();\n const [archiveDataset] = useCosArchiveDatasetMutation();\n const [updateDataset, { loading: savingTags }] = useCosUpdateDatasetMutation();\n const [addSchemaField, { loading: addingField }] = useCosAddSchemaFieldMutation();\n\n // Local, dirty-tracked copy of the tags array so we persist explicitly. Re-sync\n // from the server whenever the dataset (or its updatedAt, after a save) changes\n // — the documented derive-state-during-render pattern, no effect needed.\n const [tags, setTags] = useState<string[]>([]);\n const [syncedKey, setSyncedKey] = useState<string | null>(null);\n const datasetKey = dataset ? `${dataset.id}:${dataset.updatedAt}` : null;\n if (datasetKey && datasetKey !== syncedKey) {\n setSyncedKey(datasetKey);\n setTags(dataset?.tags ?? []);\n }\n const tagsDirty =\n dataset != null &&\n (tags.length !== dataset.tags.length || tags.some((tag, i) => tag !== dataset.tags[i]));\n\n // Add-schema-field dialog state.\n const [fieldOpen, setFieldOpen] = useState(false);\n const [fieldName, setFieldName] = useState('');\n const [fieldType, setFieldType] = useState<CosFieldType>('STRING');\n const [fieldUnit, setFieldUnit] = useState('');\n const [fieldDescription, setFieldDescription] = useState('');\n const [fieldProvenance, setFieldProvenance] = useState('');\n const [fieldNullable, setFieldNullable] = useState(true);\n\n const resetFieldForm = () => {\n setFieldName('');\n setFieldType('STRING');\n setFieldUnit('');\n setFieldDescription('');\n setFieldProvenance('');\n setFieldNullable(true);\n };\n\n const setFieldOpenAndReset = (open: boolean) => {\n setFieldOpen(open);\n if (!open) {\n resetFieldForm();\n }\n };\n\n if (loading) {\n return (\n <PageLayout title=\"Dataset\" backPath=\"datasets\">\n <LoadingState label=\"Loading dataset…\" />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout title=\"Dataset\" backPath=\"datasets\">\n <ErrorState message=\"We could not load this dataset.\" onRetry={() => void refetch()} />\n </PageLayout>\n );\n }\n\n if (!dataset) {\n return (\n <PageLayout title=\"Dataset\" backPath=\"datasets\">\n <EmptyState\n icon={Database}\n title=\"Dataset not found.\"\n description=\"This dataset may have been removed or is outside your current scope.\"\n action={\n <Button type=\"button\" onClick={() => navigate('datasets')}>\n Back to datasets\n </Button>\n }\n />\n </PageLayout>\n );\n }\n\n const schemaFields = [...(dataset.schemaFields ?? [])].sort((a, b) => a.position - b.position);\n const canPublish = dataset.status !== 'AVAILABLE' && dataset.status !== 'ARCHIVED';\n\n const handlePublish = async () => {\n const response = await publishDataset({ variables: { id: dataset.id } });\n if (response.data?.cosPublishDataset) {\n notify.success('Dataset published', `“${dataset.name}” is now available.`);\n await refetch();\n }\n };\n\n const handleArchive = async () => {\n const response = await archiveDataset({ variables: { id: dataset.id } });\n if (response.error) {\n throw new Error(response.error.message);\n }\n if (!response.data?.cosArchiveDataset) {\n notify.error('Could not archive dataset', 'The server did not confirm the change.');\n throw new Error('Archive not confirmed');\n }\n notify.success('Dataset archived');\n navigate('datasets');\n };\n\n const handleSaveTags = async () => {\n const response = await updateDataset({ variables: { id: dataset.id, input: { tags } } });\n if (response.data?.cosUpdateDataset) {\n notify.success('Tags updated');\n await refetch();\n }\n };\n\n const handleAddField = async () => {\n if (!fieldName.trim()) {\n notify.error('Field name is required');\n return;\n }\n const response = await addSchemaField({\n variables: {\n input: {\n datasetId: dataset.id,\n name: fieldName.trim(),\n fieldType,\n unit: fieldUnit.trim() || undefined,\n description: fieldDescription.trim() || undefined,\n provenance: fieldProvenance.trim() || undefined,\n nullable: fieldNullable,\n },\n },\n });\n if (response.data?.cosAddSchemaField) {\n notify.success('Schema field added');\n setFieldOpenAndReset(false);\n await refetch();\n }\n };\n\n return (\n <PageLayout\n title={dataset.name}\n description={dataset.description ?? undefined}\n backPath=\"datasets\"\n actions={\n <div className=\"flex items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => navigate(`datasets/${dataset.id}/edit`)}\n >\n <Pencil className=\"size-4\" />\n Edit\n </Button>\n {canPublish ? (\n <Button type=\"button\" onClick={() => void handlePublish()} disabled={publishing}>\n {publishing ? 'Publishing…' : 'Publish'}\n </Button>\n ) : null}\n <ActionMenu\n ariaLabel={`Actions for ${dataset.name}`}\n entityName={dataset.name}\n onDelete={() => handleArchive()}\n deleteLabel=\"Archive dataset\"\n />\n </div>\n }\n >\n <div className=\"space-y-6\">\n {/* Status + key facts */}\n <div className=\"flex flex-wrap items-center gap-2\">\n <StatusBadge status={dataset.status} />\n <StatusBadge status={dataset.accessLevel} label={formatEnumLabel(dataset.accessLevel)} />\n {dataset.lineageCaptured ? <Badge variant=\"secondary\">Lineage captured</Badge> : null}\n <Badge variant=\"secondary\">v{dataset.version}</Badge>\n </div>\n\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n <MetaTile\n label=\"Source\"\n value={\n dataset.source ? (\n <button\n type=\"button\"\n onClick={() => navigate(`sources/${dataset.source?.id}/edit`)}\n className=\"inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline\"\n >\n <Radar className=\"size-4 text-text-secondary\" aria-hidden=\"true\" />\n {dataset.source.name}\n </button>\n ) : (\n <span className=\"text-text-secondary\">Not linked</span>\n )\n }\n />\n <MetaTile\n label=\"Collection\"\n value={\n dataset.collection ? (\n <button\n type=\"button\"\n onClick={() => navigate(`collections/${dataset.collection?.id}`)}\n className=\"inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline\"\n >\n <Boxes className=\"size-4 text-text-secondary\" aria-hidden=\"true\" />\n {dataset.collection.name}\n </button>\n ) : (\n <span className=\"text-text-secondary\">Not in a collection</span>\n )\n }\n />\n <MetaTile label=\"Format\" value={<span>{dataset.format || 'Not specified'}</span>} />\n <MetaTile\n label=\"Size\"\n value={\n <span className=\"tabular-nums\">\n {formatBytes(dataset.sizeBytes)}\n {Number(dataset.rowCount) > 0 ? (\n <span className=\"text-text-secondary\">\n {' '}\n · {Number(dataset.rowCount).toLocaleString()} rows\n </span>\n ) : null}\n </span>\n }\n />\n <MetaTile label=\"Ingested\" value={<span>{formatDateTime(dataset.ingestedAt)}</span>} />\n <MetaTile label=\"Created\" value={<span>{formatDateTime(dataset.createdAt)}</span>} />\n <MetaTile label=\"Updated\" value={<span>{formatDateTime(dataset.updatedAt)}</span>} />\n <MetaTile\n label=\"Artifact\"\n value={\n dataset.file ? (\n downloadUrl ? (\n <a\n href={downloadUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline\"\n >\n <Download className=\"size-4\" aria-hidden=\"true\" />\n Download file\n </a>\n ) : (\n <span className=\"text-text-secondary\">Resolving link…</span>\n )\n ) : (\n <span className=\"text-text-secondary\">No file attached</span>\n )\n }\n />\n </div>\n\n {/* Schema fields */}\n <section className=\"space-y-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2\">\n <Columns3 className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">Schema fields</h2>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setFieldOpenAndReset(true)}\n >\n <Plus className=\"size-4\" />\n Add field\n </Button>\n </div>\n\n {schemaFields.length === 0 ? (\n <EmptyState\n icon={Columns3}\n title=\"No schema fields yet.\"\n description=\"Describe the columns in this dataset so consumers know what each field means.\"\n />\n ) : (\n <div className=\"rounded-card border border-border-default bg-bg-elevated\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Name</TableHead>\n <TableHead>Type</TableHead>\n <TableHead>Unit</TableHead>\n <TableHead>Nullable</TableHead>\n <TableHead>Provenance</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {schemaFields.map((field) => (\n <TableRow key={field.id}>\n <TableCell>\n <span className=\"font-medium text-text-primary\">{field.name}</span>\n {field.description ? (\n <p className=\"mt-0.5 line-clamp-1 max-w-xs text-xs text-text-secondary\">\n {field.description}\n </p>\n ) : null}\n </TableCell>\n <TableCell>\n <Badge variant=\"secondary\">{formatEnumLabel(field.fieldType)}</Badge>\n </TableCell>\n <TableCell className=\"text-sm text-text-secondary\">\n {field.unit || '—'}\n </TableCell>\n <TableCell className=\"text-sm text-text-secondary\">\n {field.nullable ? 'Yes' : 'No'}\n </TableCell>\n <TableCell className=\"text-sm text-text-secondary\">\n {field.provenance || '—'}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </section>\n\n {/* Tags */}\n <section className=\"space-y-3 rounded-card border border-border-default bg-bg-elevated p-5\">\n <EntityTagsField value={tags} onChange={setTags} label=\"Dataset tags\" />\n {tagsDirty ? (\n <div className=\"flex justify-end\">\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void handleSaveTags()}\n disabled={savingTags}\n >\n {savingTags ? 'Saving…' : 'Save tags'}\n </Button>\n </div>\n ) : null}\n </section>\n\n {/* Discuss */}\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <MessagesSquare className=\"size-4\" aria-hidden=\"true\" />\n <span>Questions about this dataset?</span>\n <SafeLink\n href=\"/conversations\"\n className=\"text-text-primary underline-offset-2 hover:underline\"\n >\n Discuss in conversations\n </SafeLink>\n </div>\n </div>\n\n {/* Add schema field dialog */}\n <Dialog open={fieldOpen} onOpenChange={setFieldOpenAndReset}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Add schema field</DialogTitle>\n <DialogDescription>\n Document a column in “{dataset.name}” — its type, unit and provenance.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-name\">Name</Label>\n <Input\n id=\"cos-field-name\"\n value={fieldName}\n onChange={(event) => setFieldName(event.target.value)}\n placeholder=\"e.g. right_ascension\"\n required\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-type\">Type</Label>\n <Select\n value={fieldType}\n onValueChange={(value) => setFieldType(value as CosFieldType)}\n >\n <SelectTrigger id=\"cos-field-type\" aria-label=\"Field type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {FIELD_TYPES.map((type) => (\n <SelectItem key={type} value={type}>\n {formatEnumLabel(type)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-unit\">Unit</Label>\n <Input\n id=\"cos-field-unit\"\n value={fieldUnit}\n onChange={(event) => setFieldUnit(event.target.value)}\n placeholder=\"e.g. deg, mag, Jy\"\n />\n </div>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-desc\">Description</Label>\n <Textarea\n id=\"cos-field-desc\"\n value={fieldDescription}\n onChange={(event) => setFieldDescription(event.target.value)}\n rows={2}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-prov\">Provenance</Label>\n <Input\n id=\"cos-field-prov\"\n value={fieldProvenance}\n onChange={(event) => setFieldProvenance(event.target.value)}\n placeholder=\"Where this field comes from\"\n />\n </div>\n\n <label className=\"flex items-center gap-2 text-sm text-text-primary\">\n <Checkbox\n checked={fieldNullable}\n onCheckedChange={(checked) => setFieldNullable(checked === true)}\n />\n Nullable (may contain empty values)\n </label>\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setFieldOpenAndReset(false)}\n disabled={addingField}\n >\n Cancel\n </Button>\n <Button type=\"button\" onClick={() => void handleAddField()} disabled={addingField}>\n {addingField ? 'Adding…' : 'Add field'}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DatasetDetailPage.js","names":[],"sources":["../../../../src/cosmicintersection/pages/datasets/DatasetDetailPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowRight,\n Boxes,\n Columns3,\n Database,\n Download,\n GitBranch,\n History,\n MessagesSquare,\n Pencil,\n Plus,\n Radar,\n Share2,\n} from 'lucide-react';\nimport {\n Badge,\n Button,\n Checkbox,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n useCosAddSchemaFieldMutation,\n useCosAnalysesQuery,\n useCosArchiveDatasetMutation,\n useCosDatasetQuery,\n useCosNotebooksQuery,\n useCosPublishDatasetMutation,\n useCosReleasesQuery,\n useCosRunsQuery,\n useCosUpdateDatasetMutation,\n type CosCollection,\n type CosFieldType,\n type CosSource,\n} from '../../api/cosmicApi';\nimport {\n ActionMenu,\n ActivityFeedPanel,\n DiscussionPanel,\n EmptyState,\n EntityTagsField,\n ErrorState,\n LoadingState,\n PageLayout,\n StatusBadge,\n formatEnumLabel,\n useFileDownloadUrl,\n} from '../../components';\nimport {\n LineageGraph,\n buildDatasetLineage,\n type LineageDataPools,\n} from '../../components/LineageGraph';\nimport { useCosmicIntersection } from '../../context/CosmicIntersectionContext';\nimport { notify } from '../../lib/toast';\n\nconst FIELD_TYPES: CosFieldType[] = [\n 'STRING',\n 'INTEGER',\n 'FLOAT',\n 'BOOLEAN',\n 'TIMESTAMP',\n 'COORDINATE',\n 'SPECTRUM',\n 'GEOMETRY',\n 'IMAGE_REF',\n 'JSON',\n];\n\nfunction formatBytes(raw: string | null | undefined): string {\n if (!raw) {\n return '—';\n }\n const bytes = Number(raw);\n if (!Number.isFinite(bytes) || bytes <= 0) {\n return '—';\n }\n const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];\n let value = bytes;\n let unit = 0;\n while (value >= 1024 && unit < units.length - 1) {\n value /= 1024;\n unit += 1;\n }\n return `${value >= 10 || unit === 0 ? Math.round(value) : value.toFixed(1)} ${units[unit]}`;\n}\n\nfunction formatDateTime(raw: string | null | undefined): string {\n if (!raw) {\n return '—';\n }\n const date = new Date(raw);\n return Number.isNaN(date.getTime()) ? '—' : date.toLocaleString();\n}\n\nfunction MetaTile({ label, value }: { label: string; value: React.ReactNode }) {\n return (\n <div className=\"rounded-card border border-border-default bg-bg-elevated p-4\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">{label}</p>\n <div className=\"mt-1 text-sm text-text-primary\">{value}</div>\n </div>\n );\n}\n\nexport default function DatasetDetailPage() {\n const { id = '' } = useParams<{ id: string }>();\n const { navigate } = useCosmicIntersection();\n\n const { data, loading, error, refetch } = useCosDatasetQuery(id);\n const dataset = data?.cosDataset ?? null;\n\n const download = useFileDownloadUrl(dataset?.file?.id);\n const downloadUrl = download.data?.getFileDownloadUrl ?? null;\n\n const [publishDataset, { loading: publishing }] = useCosPublishDatasetMutation();\n const [archiveDataset] = useCosArchiveDatasetMutation();\n const [updateDataset, { loading: savingTags }] = useCosUpdateDatasetMutation();\n const [addSchemaField, { loading: addingField }] = useCosAddSchemaFieldMutation();\n\n // Lineage inputs — fetched as lists and filtered client-side to this dataset,\n // then folded into a provenance model by the shared builder. No new backend.\n const analysesQuery = useCosAnalysesQuery({ datasetId: id });\n const runsQuery = useCosRunsQuery({ pagination: { limit: 100, offset: 0 } });\n const notebooksQuery = useCosNotebooksQuery({ pagination: { limit: 100, offset: 0 } });\n const releasesQuery = useCosReleasesQuery({ pagination: { limit: 100, offset: 0 } });\n\n const lineageDataset = data?.cosDataset ?? null;\n const lineageModel = useMemo(() => {\n if (!lineageDataset) {\n return { nodes: [], edges: [] };\n }\n const sourcesById = new Map<string, CosSource>();\n if (lineageDataset.source) {\n sourcesById.set(lineageDataset.source.id, lineageDataset.source);\n }\n const collectionsById = new Map<string, CosCollection>();\n if (lineageDataset.collection) {\n collectionsById.set(lineageDataset.collection.id, lineageDataset.collection);\n }\n const pools: LineageDataPools = {\n datasetsById: new Map([[lineageDataset.id, lineageDataset]]),\n sourcesById,\n collectionsById,\n runs: (runsQuery.data?.cosListRuns?.items ?? []).filter(\n (run) => run.datasetId === lineageDataset.id\n ),\n notebooks: (notebooksQuery.data?.cosListNotebooks?.items ?? []).filter((notebook) =>\n notebook.datasetIds.includes(lineageDataset.id)\n ),\n analyses: analysesQuery.data?.cosListAnalyses ?? [],\n releases: (releasesQuery.data?.cosListReleases?.items ?? []).filter((release) =>\n release.datasetIds.includes(lineageDataset.id)\n ),\n };\n return buildDatasetLineage(lineageDataset.id, pools);\n }, [lineageDataset, runsQuery.data, notebooksQuery.data, analysesQuery.data, releasesQuery.data]);\n const lineageListsLoading =\n runsQuery.loading || notebooksQuery.loading || analysesQuery.loading || releasesQuery.loading;\n\n // Local, dirty-tracked copy of the tags array so we persist explicitly. Re-sync\n // from the server whenever the dataset (or its updatedAt, after a save) changes\n // — the documented derive-state-during-render pattern, no effect needed.\n const [tags, setTags] = useState<string[]>([]);\n const [syncedKey, setSyncedKey] = useState<string | null>(null);\n const datasetKey = dataset ? `${dataset.id}:${dataset.updatedAt}` : null;\n if (datasetKey && datasetKey !== syncedKey) {\n setSyncedKey(datasetKey);\n setTags(dataset?.tags ?? []);\n }\n const tagsDirty =\n dataset != null &&\n (tags.length !== dataset.tags.length || tags.some((tag, i) => tag !== dataset.tags[i]));\n\n // Add-schema-field dialog state.\n const [fieldOpen, setFieldOpen] = useState(false);\n const [fieldName, setFieldName] = useState('');\n const [fieldType, setFieldType] = useState<CosFieldType>('STRING');\n const [fieldUnit, setFieldUnit] = useState('');\n const [fieldDescription, setFieldDescription] = useState('');\n const [fieldProvenance, setFieldProvenance] = useState('');\n const [fieldNullable, setFieldNullable] = useState(true);\n\n const resetFieldForm = () => {\n setFieldName('');\n setFieldType('STRING');\n setFieldUnit('');\n setFieldDescription('');\n setFieldProvenance('');\n setFieldNullable(true);\n };\n\n const setFieldOpenAndReset = (open: boolean) => {\n setFieldOpen(open);\n if (!open) {\n resetFieldForm();\n }\n };\n\n if (loading) {\n return (\n <PageLayout title=\"Dataset\" backPath=\"datasets\">\n <LoadingState label=\"Loading dataset…\" />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout title=\"Dataset\" backPath=\"datasets\">\n <ErrorState message=\"We could not load this dataset.\" onRetry={() => void refetch()} />\n </PageLayout>\n );\n }\n\n if (!dataset) {\n return (\n <PageLayout title=\"Dataset\" backPath=\"datasets\">\n <EmptyState\n icon={Database}\n title=\"Dataset not found.\"\n description=\"This dataset may have been removed or is outside your current scope.\"\n action={\n <Button type=\"button\" onClick={() => navigate('datasets')}>\n Back to datasets\n </Button>\n }\n />\n </PageLayout>\n );\n }\n\n const schemaFields = [...(dataset.schemaFields ?? [])].sort((a, b) => a.position - b.position);\n const canPublish = dataset.status !== 'AVAILABLE' && dataset.status !== 'ARCHIVED';\n\n const handlePublish = async () => {\n const response = await publishDataset({ variables: { id: dataset.id } });\n if (response.data?.cosPublishDataset) {\n notify.success('Dataset published', `“${dataset.name}” is now available.`);\n await refetch();\n }\n };\n\n const handleArchive = async () => {\n const response = await archiveDataset({ variables: { id: dataset.id } });\n if (response.error) {\n throw new Error(response.error.message);\n }\n if (!response.data?.cosArchiveDataset) {\n notify.error('Could not archive dataset', 'The server did not confirm the change.');\n throw new Error('Archive not confirmed');\n }\n notify.success('Dataset archived');\n navigate('datasets');\n };\n\n const handleSaveTags = async () => {\n const response = await updateDataset({ variables: { id: dataset.id, input: { tags } } });\n if (response.data?.cosUpdateDataset) {\n notify.success('Tags updated');\n await refetch();\n }\n };\n\n const handleAddField = async () => {\n if (!fieldName.trim()) {\n notify.error('Field name is required');\n return;\n }\n const response = await addSchemaField({\n variables: {\n input: {\n datasetId: dataset.id,\n name: fieldName.trim(),\n fieldType,\n unit: fieldUnit.trim() || undefined,\n description: fieldDescription.trim() || undefined,\n provenance: fieldProvenance.trim() || undefined,\n nullable: fieldNullable,\n },\n },\n });\n if (response.data?.cosAddSchemaField) {\n notify.success('Schema field added');\n setFieldOpenAndReset(false);\n await refetch();\n }\n };\n\n return (\n <PageLayout\n title={dataset.name}\n description={dataset.description ?? undefined}\n backPath=\"datasets\"\n actions={\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => navigate(`datasets/${dataset.id}/edit`)}\n >\n <Pencil className=\"size-4\" />\n Edit\n </Button>\n {canPublish ? (\n <Button type=\"button\" onClick={() => void handlePublish()} disabled={publishing}>\n {publishing ? 'Publishing…' : 'Publish'}\n </Button>\n ) : null}\n <ActionMenu\n ariaLabel={`Actions for ${dataset.name}`}\n entityName={dataset.name}\n onDelete={() => handleArchive()}\n deleteLabel=\"Archive dataset\"\n />\n </div>\n }\n >\n <div className=\"space-y-6\">\n {/* Status + key facts */}\n <div className=\"flex flex-wrap items-center gap-2\">\n <StatusBadge status={dataset.status} />\n <StatusBadge status={dataset.accessLevel} label={formatEnumLabel(dataset.accessLevel)} />\n <span\n className=\"inline-flex items-center gap-1.5 rounded-full border border-border-default bg-bg-elevated px-2.5 py-0.5 text-xs font-medium\"\n title=\"Current dataset version\"\n >\n <GitBranch className=\"size-3.5 text-text-tertiary\" aria-hidden=\"true\" />\n <span className=\"text-text-primary\">v{dataset.version}</span>\n <span className=\"text-text-tertiary\">· current</span>\n </span>\n </div>\n\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n <MetaTile\n label=\"Source\"\n value={\n dataset.source ? (\n <button\n type=\"button\"\n onClick={() => navigate(`sources/${dataset.source?.id}`)}\n className=\"inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline\"\n >\n <Radar className=\"size-4 text-text-secondary\" aria-hidden=\"true\" />\n {dataset.source.name}\n </button>\n ) : (\n <span className=\"text-text-secondary\">Not linked</span>\n )\n }\n />\n <MetaTile\n label=\"Collection\"\n value={\n dataset.collection ? (\n <button\n type=\"button\"\n onClick={() => navigate(`collections/${dataset.collection?.id}`)}\n className=\"inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline\"\n >\n <Boxes className=\"size-4 text-text-secondary\" aria-hidden=\"true\" />\n {dataset.collection.name}\n </button>\n ) : (\n <span className=\"text-text-secondary\">Not in a collection</span>\n )\n }\n />\n <MetaTile label=\"Format\" value={<span>{dataset.format || 'Not specified'}</span>} />\n <MetaTile\n label=\"Size\"\n value={\n <span className=\"tabular-nums\">\n {formatBytes(dataset.sizeBytes)}\n {Number(dataset.rowCount) > 0 ? (\n <span className=\"text-text-secondary\">\n {' '}\n · {Number(dataset.rowCount).toLocaleString()} rows\n </span>\n ) : null}\n </span>\n }\n />\n <MetaTile label=\"Ingested\" value={<span>{formatDateTime(dataset.ingestedAt)}</span>} />\n <MetaTile label=\"Created\" value={<span>{formatDateTime(dataset.createdAt)}</span>} />\n <MetaTile label=\"Updated\" value={<span>{formatDateTime(dataset.updatedAt)}</span>} />\n <MetaTile\n label=\"Artifact\"\n value={\n dataset.file ? (\n downloadUrl ? (\n <a\n href={downloadUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline\"\n >\n <Download className=\"size-4\" aria-hidden=\"true\" />\n Download file\n </a>\n ) : (\n <span className=\"text-text-secondary\">Resolving link…</span>\n )\n ) : (\n <span className=\"text-text-secondary\">No file attached</span>\n )\n }\n />\n </div>\n\n {/* Lineage / provenance */}\n <section className=\"space-y-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2\">\n <Share2 className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">Lineage</h2>\n </div>\n <button\n type=\"button\"\n onClick={() => navigate(`lineage/${dataset.id}`)}\n className=\"inline-flex items-center gap-1 rounded-button text-sm font-medium text-text-link underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border-focus\"\n >\n View full lineage\n <ArrowRight className=\"size-4\" aria-hidden=\"true\" />\n </button>\n </div>\n {lineageListsLoading && lineageModel.nodes.length <= 1 ? (\n <LoadingState label=\"Building lineage…\" />\n ) : lineageModel.nodes.length <= 1 ? (\n <div className=\"rounded-card border border-dashed border-border-default bg-bg-sunken p-6 text-sm text-text-secondary\">\n No upstream or downstream provenance is linked to this dataset yet. Connect a source,\n run a pipeline, attach a notebook, or publish a release to build its lineage.\n </div>\n ) : (\n <LineageGraph model={lineageModel} mode=\"compact\" onNavigate={navigate} />\n )}\n </section>\n\n {/* Schema fields */}\n <section className=\"space-y-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2\">\n <Columns3 className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">Schema fields</h2>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setFieldOpenAndReset(true)}\n >\n <Plus className=\"size-4\" />\n Add field\n </Button>\n </div>\n\n {schemaFields.length === 0 ? (\n <EmptyState\n icon={Columns3}\n title=\"No schema fields yet.\"\n description=\"Describe the columns in this dataset so consumers know what each field means.\"\n />\n ) : (\n <>\n {/* Desktop table */}\n <div className=\"hidden rounded-card border border-border-default bg-bg-elevated md:block\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Name</TableHead>\n <TableHead>Type</TableHead>\n <TableHead>Unit</TableHead>\n <TableHead>Nullable</TableHead>\n <TableHead>Provenance</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {schemaFields.map((field) => (\n <TableRow key={field.id}>\n <TableCell>\n <span className=\"font-medium text-text-primary\">{field.name}</span>\n {field.description ? (\n <p className=\"mt-0.5 line-clamp-1 max-w-xs text-xs text-text-secondary\">\n {field.description}\n </p>\n ) : null}\n </TableCell>\n <TableCell>\n <Badge variant=\"secondary\">{formatEnumLabel(field.fieldType)}</Badge>\n </TableCell>\n <TableCell className=\"text-sm text-text-secondary\">\n {field.unit || '—'}\n </TableCell>\n <TableCell className=\"text-sm text-text-secondary\">\n {field.nullable ? 'Yes' : 'No'}\n </TableCell>\n <TableCell className=\"text-sm text-text-secondary\">\n {field.provenance || '—'}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n\n {/* Mobile card list */}\n <div className=\"space-y-2 md:hidden\">\n {schemaFields.map((field) => (\n <div\n key={field.id}\n className=\"rounded-card border border-border-default bg-bg-elevated p-3\"\n >\n <div className=\"flex items-start justify-between gap-2\">\n <span className=\"font-medium text-text-primary\">{field.name}</span>\n <Badge variant=\"secondary\">{formatEnumLabel(field.fieldType)}</Badge>\n </div>\n {field.description ? (\n <p className=\"mt-1 text-xs text-text-secondary\">{field.description}</p>\n ) : null}\n <dl className=\"mt-2 grid grid-cols-2 gap-2 text-xs\">\n <div>\n <dt className=\"text-text-tertiary\">Unit</dt>\n <dd className=\"text-text-secondary\">{field.unit || '—'}</dd>\n </div>\n <div>\n <dt className=\"text-text-tertiary\">Nullable</dt>\n <dd className=\"text-text-secondary\">{field.nullable ? 'Yes' : 'No'}</dd>\n </div>\n <div className=\"col-span-2\">\n <dt className=\"text-text-tertiary\">Provenance</dt>\n <dd className=\"text-text-secondary\">{field.provenance || '—'}</dd>\n </div>\n </dl>\n </div>\n ))}\n </div>\n </>\n )}\n </section>\n\n {/* Tags */}\n <section className=\"space-y-3 rounded-card border border-border-default bg-bg-elevated p-5\">\n <EntityTagsField value={tags} onChange={setTags} label=\"Dataset tags\" />\n {tagsDirty ? (\n <div className=\"flex justify-end\">\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void handleSaveTags()}\n disabled={savingTags}\n >\n {savingTags ? 'Saving…' : 'Save tags'}\n </Button>\n </div>\n ) : null}\n </section>\n\n {/* Activity / history */}\n <section className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <History className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">Activity</h2>\n </div>\n <ActivityFeedPanel resourceId={dataset.id} resourceType=\"cosmicintersection-dataset\" />\n </section>\n\n {/* Discussion */}\n <section className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <MessagesSquare className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">Discussion</h2>\n </div>\n <DiscussionPanel\n entityType=\"cosmicintersection-dataset\"\n entityId={dataset.id}\n title={dataset.name}\n widgetKey=\"dataset-discussion\"\n />\n </section>\n </div>\n\n {/* Add schema field dialog */}\n <Dialog open={fieldOpen} onOpenChange={setFieldOpenAndReset}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Add schema field</DialogTitle>\n <DialogDescription>\n Document a column in “{dataset.name}” — its type, unit and provenance.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-name\">Name</Label>\n <Input\n id=\"cos-field-name\"\n value={fieldName}\n onChange={(event) => setFieldName(event.target.value)}\n placeholder=\"e.g. right_ascension\"\n required\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-type\">Type</Label>\n <Select\n value={fieldType}\n onValueChange={(value) => setFieldType(value as CosFieldType)}\n >\n <SelectTrigger id=\"cos-field-type\" aria-label=\"Field type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {FIELD_TYPES.map((type) => (\n <SelectItem key={type} value={type}>\n {formatEnumLabel(type)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-unit\">Unit</Label>\n <Input\n id=\"cos-field-unit\"\n value={fieldUnit}\n onChange={(event) => setFieldUnit(event.target.value)}\n placeholder=\"e.g. deg, mag, Jy\"\n />\n </div>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-desc\">Description</Label>\n <Textarea\n id=\"cos-field-desc\"\n value={fieldDescription}\n onChange={(event) => setFieldDescription(event.target.value)}\n rows={2}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-prov\">Provenance</Label>\n <Input\n id=\"cos-field-prov\"\n value={fieldProvenance}\n onChange={(event) => setFieldProvenance(event.target.value)}\n placeholder=\"Where this field comes from\"\n />\n </div>\n\n <label className=\"flex items-center gap-2 text-sm text-text-primary\">\n <Checkbox\n checked={fieldNullable}\n onCheckedChange={(checked) => setFieldNullable(checked === true)}\n />\n Nullable (may contain empty values)\n </label>\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setFieldOpenAndReset(false)}\n disabled={addingField}\n >\n Cancel\n </Button>\n <Button type=\"button\" onClick={() => void handleAddField()} disabled={addingField}>\n {addingField ? 'Adding…' : 'Add field'}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { useCosmicIntersection as e } from "../../context/CosmicIntersectionContext.js";
|
|
2
2
|
import { notify as t } from "../../lib/toast.js";
|
|
3
3
|
import { useCosCollectionsQuery as n, useCosCreateDatasetMutation as r, useCosDatasetQuery as i, useCosSourcesQuery as a, useCosUpdateDatasetMutation as o } from "../../api/cosmicApi.js";
|
|
4
|
-
import s from "../../components/
|
|
5
|
-
import c from "../../components/
|
|
6
|
-
import l from "../../components/
|
|
7
|
-
import u from "../../components/
|
|
4
|
+
import s from "../../components/LoadingState.js";
|
|
5
|
+
import c from "../../components/EntityFormShell.js";
|
|
6
|
+
import l from "../../components/EntityTagsField.js";
|
|
7
|
+
import u from "../../components/FileUploadField.js";
|
|
8
8
|
import { formatEnumLabel as d } from "../../components/StatusBadge.js";
|
|
9
9
|
import "../../components/index.js";
|
|
10
10
|
import { useMemo as f, useState as p } from "react";
|
|
@@ -51,7 +51,7 @@ function O() {
|
|
|
51
51
|
[e]: t
|
|
52
52
|
}));
|
|
53
53
|
}, W = N.data?.cosListSources?.items ?? [], G = P.data?.cosListCollections ?? [], K = I || R;
|
|
54
|
-
return k && M && !j?.cosDataset ? /* @__PURE__ */ m(
|
|
54
|
+
return k && M && !j?.cosDataset ? /* @__PURE__ */ m(s, { label: "Loading dataset…" }) : /* @__PURE__ */ h(c, {
|
|
55
55
|
title: k ? "Edit dataset" : "New dataset",
|
|
56
56
|
description: "Register a federated science dataset with its access level, source and schema.",
|
|
57
57
|
purpose: "Datasets are the core unit of federation — catalog the data once, describe where it comes from and how it can be accessed, then reuse it across pipelines, notebooks and releases.",
|
|
@@ -195,14 +195,14 @@ function O() {
|
|
|
195
195
|
})
|
|
196
196
|
]
|
|
197
197
|
}),
|
|
198
|
-
/* @__PURE__ */ m(
|
|
198
|
+
/* @__PURE__ */ m(l, {
|
|
199
199
|
value: z.tags,
|
|
200
200
|
onChange: (e) => U("tags", e),
|
|
201
201
|
label: "Tags"
|
|
202
202
|
}),
|
|
203
203
|
k ? null : /* @__PURE__ */ h("div", {
|
|
204
204
|
className: "space-y-1.5",
|
|
205
|
-
children: [/* @__PURE__ */ m(v, { children: "Data file" }), /* @__PURE__ */ m(
|
|
205
|
+
children: [/* @__PURE__ */ m(v, { children: "Data file" }), /* @__PURE__ */ m(u, {
|
|
206
206
|
value: z.fileId,
|
|
207
207
|
onChange: (e) => U("fileId", e),
|
|
208
208
|
label: "Upload data file",
|