From cf7496aea1770fa9c7cc1d947ba045054dc1fef0 Mon Sep 17 00:00:00 2001 From: Nick Lucas Date: Mon, 15 Dec 2025 13:54:15 +0000 Subject: [PATCH 01/36] WIP --- plugins/csv-import/src/App.css | 133 +++++++++ plugins/csv-import/src/App.tsx | 333 ++++++++--------------- plugins/csv-import/src/FieldMapping.tsx | 235 ++++++++++++++++ plugins/csv-import/src/SelectCSVFile.tsx | 160 +++++++++++ plugins/csv-import/src/csv.ts | 152 +++++++++++ plugins/csv-import/src/typeInference.ts | 159 +++++++++++ 6 files changed, 958 insertions(+), 214 deletions(-) create mode 100644 plugins/csv-import/src/FieldMapping.tsx create mode 100644 plugins/csv-import/src/SelectCSVFile.tsx create mode 100644 plugins/csv-import/src/typeInference.ts diff --git a/plugins/csv-import/src/App.css b/plugins/csv-import/src/App.css index 2dbf6932d..83c343da1 100644 --- a/plugins/csv-import/src/App.css +++ b/plugins/csv-import/src/App.css @@ -21,6 +21,16 @@ position: relative; } +.select-csv-file { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + flex: 1; + position: relative; +} + .manage-conflicts { gap: 10px; } @@ -202,3 +212,126 @@ width: fit-content; color: var(--framer-color-text-secondary); } + +/* Field Mapping */ + +.mapping { + padding: 0 15px 0; + height: 100%; +} + +.mapping form { + height: 100%; + display: flex; + flex-direction: column; +} + +.mapping .sticky-divider { + position: sticky; + top: 0; + margin: 0 -15px 15px; + border: none; + border-top: 1px solid var(--framer-color-divider); +} + +.mapping .slug-field { + display: flex; + flex-direction: column; + width: 100%; + justify-content: space-between; + gap: 10px; + color: var(--framer-color-text-tertiary); + padding-bottom: 10px; +} + +.mapping .fields { + display: grid; + grid-template-columns: 1fr 8px 1fr 1fr; + gap: 10px; + margin-bottom: auto; + padding-bottom: 10px; + align-items: center; + color: var(--framer-color-text-tertiary); +} + +.mapping .fields-column { + grid-column: span 2 / span 2; +} + +.mapping .source-field { + display: flex; + flex-direction: row; + align-items: center; + justify-content: left; + white-space: nowrap; + font-weight: 500; + background-color: var(--framer-color-bg-tertiary); + gap: 8px; + padding: 0 10px; + height: 30px; + border-radius: 8px; +} + +.mapping .source-field[aria-disabled="true"] { + opacity: 0.5; +} + +.mapping .source-field:focus-visible { + outline: none; + box-shadow: inset 0 0 0 1px var(--framer-color-tint); +} + +.mapping .source-field input[type="checkbox"] { + cursor: pointer; +} + +.mapping .source-field input[type="checkbox"]:focus { + box-shadow: none; +} + +[data-framer-theme="light"] .mapping .source-field input[type="checkbox"]:not(:checked) { + background: #ccc; +} + +[data-framer-theme="dark"] .mapping .source-field input[type="checkbox"]:not(:checked) { + background: #666; +} + +.mapping .field-type { + width: 100%; +} + +.mapping .field-input { + width: 100%; + flex-shrink: 1; +} + +.mapping .field-input[disabled] { + opacity: 0.5; +} + +.mapping footer { + position: sticky; + bottom: 0; + left: 0; + width: 100%; + background-color: var(--framer-color-bg); + margin-top: auto; + padding-bottom: 15px; + display: flex; + flex-direction: column; + gap: 15px; +} + +.mapping footer .sticky-top { + border: none; + border-top: 1px solid var(--framer-color-divider); +} + +select:disabled { + opacity: 0.5; +} + +select:not(:disabled) { + cursor: pointer; +} diff --git a/plugins/csv-import/src/App.tsx b/plugins/csv-import/src/App.tsx index c6270783e..02a107a27 100644 --- a/plugins/csv-import/src/App.tsx +++ b/plugins/csv-import/src/App.tsx @@ -1,76 +1,85 @@ import type { Collection } from "framer-plugin" import { FramerPluginClosedError, framer, useIsAllowedTo } from "framer-plugin" -import { type ChangeEvent, useCallback, useEffect, useMemo, useRef, useState } from "react" +import { useCallback, useEffect, useMemo, useState } from "react" import type { ImportResult } from "./csv" import "./App.css" import { CollectionSelector } from "./CollectionSelector" -import { ImportError, importCSV, parseCSV, processRecords } from "./csv" -import { ImportIcon } from "./ImportIcon" +import { ImportError, importCSV, parseCSV, processRecordsWithFieldMapping } from "./csv" +import { FieldMapping } from "./FieldMapping" import { ManageConflicts } from "./ManageConflicts" +import { SelectCSVFile } from "./SelectCSVFile" +import type { InferredField } from "./typeInference" +import { inferFieldsFromCSV } from "./typeInference" + +type WorkflowStep = "select-collection" | "select-file" | "field-mapping" | "manage-conflicts" export function App({ initialCollection }: { initialCollection: Collection | null }) { const [collection, setCollection] = useState(initialCollection) - const isAllowedToAddItems = useIsAllowedTo("Collection.addItems") - const form = useRef(null) - const inputOpenedFromImportButton = useRef(false) - + const [workflowStep, setWorkflowStep] = useState( + initialCollection ? "select-file" : "select-collection" + ) + const [csvRecords, setCsvRecords] = useState[]>([]) + const [inferredFields, setInferredFields] = useState([]) const [result, setResult] = useState(null) const itemsWithConflict = useMemo(() => result?.items.filter(item => item.action === "conflict") ?? [], [result]) - const [isDragging, setIsDragging] = useState(false) - useEffect(() => { - void framer.showUI({ - width: 260, - height: 330, - resizable: false, - }) - }, []) + // Adjust UI size based on workflow step + if (workflowStep === "field-mapping") { + void framer.showUI({ + width: 400, + height: 600, + resizable: true, + }) + } else if (workflowStep === "manage-conflicts") { + void framer.showUI({ + width: 260, + height: 165, + resizable: false, + }) + } else { + void framer.showUI({ + width: 260, + height: 330, + resizable: false, + }) + } + }, [workflowStep]) useEffect(() => { - if (itemsWithConflict.length === 0) { - return + // Update workflow step based on collection selection + if (collection && workflowStep === "select-collection") { + setWorkflowStep("select-file") } + }, [collection, workflowStep]) - void framer.showUI({ - width: 260, - height: 165, - resizable: false, - }) - }, [itemsWithConflict]) - - const importItems = useCallback( - async (result: ImportResult) => { - if (!collection) return - - await framer.hideUI() - await importCSV(collection, result) - }, - [collection] - ) + useEffect(() => { + // Update workflow step when conflicts are detected + if (itemsWithConflict.length > 0 && workflowStep !== "manage-conflicts") { + setWorkflowStep("manage-conflicts") + } + }, [itemsWithConflict, workflowStep]) - const processAndImport = useCallback( - async (csv: string) => { + const handleFileSelected = useCallback( + async (csvContent: string) => { if (!collection) return if (!isAllowedToAddItems) return try { - const csvRecords = await parseCSV(csv) - if (csvRecords.length === 0) { + const records = await parseCSV(csvContent) + if (records.length === 0) { throw new Error("No records found in CSV") } - const result = await processRecords(collection, csvRecords) - setResult(result) - - if (result.items.some(item => item.action === "conflict")) { - return - } + // Infer field types from CSV data + const fields = inferFieldsFromCSV(records) - await importItems(result) + setCsvRecords(records) + setInferredFields(fields) + setWorkflowStep("field-mapping") } catch (error) { if (error instanceof FramerPluginClosedError) throw error @@ -81,139 +90,65 @@ export function App({ initialCollection }: { initialCollection: Collection | nul return } - framer.closePlugin("Error processing CSV file. Check console for details.", { + framer.notify("Error processing CSV file. Check console for details.", { variant: "error", }) } }, - [isAllowedToAddItems, collection, importItems] + [collection, isAllowedToAddItems] ) - useEffect(() => { - if (!collection) return - if (!isAllowedToAddItems) return - - const formElement = form.current - if (!formElement) return - - const handleDragOver = (event: DragEvent) => { - event.preventDefault() - setIsDragging(true) - } - - const handleDragLeave = (event: DragEvent) => { - if (!event.relatedTarget) { - setIsDragging(false) - } - } - - const handleDrop = (event: DragEvent) => { - event.preventDefault() - setIsDragging(false) - - const file = event.dataTransfer?.files[0] - if (!file?.name.endsWith(".csv")) return - - const input = document.getElementById("file-input") as HTMLInputElement - const dataTransfer = new DataTransfer() - dataTransfer.items.add(file) - input.files = dataTransfer.files - formElement.requestSubmit() - } - - formElement.addEventListener("dragover", handleDragOver) - formElement.addEventListener("dragleave", handleDragLeave) - formElement.addEventListener("drop", handleDrop) - - return () => { - formElement.removeEventListener("dragover", handleDragOver) - formElement.removeEventListener("dragleave", handleDragLeave) - formElement.removeEventListener("drop", handleDrop) - } - }, [isAllowedToAddItems, collection]) + const handleFieldMappingSubmit = useCallback( + async (fields: InferredField[], ignoredFieldNames: Set, slugFieldName: string) => { + if (!collection) return + if (!isAllowedToAddItems) return - useEffect(() => { - if (!collection) return - if (!isAllowedToAddItems) return + try { + const result = await processRecordsWithFieldMapping( + collection, + csvRecords, + fields, + ignoredFieldNames, + slugFieldName + ) + setResult(result) - const handlePaste = (event: ClipboardEvent) => { - const { clipboardData } = event - if (!clipboardData) return + if (result.items.some(item => item.action === "conflict")) { + return + } - // Check if the paste event originated from within an input element - const target = event.target as HTMLElement - if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") { - return - } + await framer.hideUI() + await importCSV(collection, result) + } catch (error) { + if (error instanceof FramerPluginClosedError) throw error - const task = async () => { - let csv = "" + console.error(error) - try { - csv = clipboardData.getData("text/plain") - if (!csv) return - } catch (error) { - console.error("Error accessing clipboard data:", error) - framer.notify("Unable to access clipboard content", { - variant: "error", - }) + if (error instanceof ImportError || error instanceof Error) { + framer.notify(error.message, { variant: "error" }) return } - try { - await processAndImport(csv) - } catch (error) { - if (error instanceof FramerPluginClosedError) return - - console.error("Error importing CSV:", error) - framer.notify("Error importing CSV", { - variant: "error", - }) - } + framer.notify("Error processing CSV file. Check console for details.", { + variant: "error", + }) } - - void task() - } - - window.addEventListener("paste", handlePaste) - - return () => { - window.removeEventListener("paste", handlePaste) - } - }, [isAllowedToAddItems, processAndImport, collection]) - - const handleSubmit = useCallback( - (event: React.FormEvent) => { - if (!collection) return - if (!isAllowedToAddItems) return - event.preventDefault() - - if (!form.current) throw new Error("Form ref not set") - - const formData = new FormData(form.current) - const fileValue = formData.get("file") - - if (!fileValue || typeof fileValue === "string") return - - const file = fileValue - - void file.text().then(processAndImport) }, - [isAllowedToAddItems, processAndImport, collection] + [collection, csvRecords, isAllowedToAddItems] ) - const handleFileChange = useCallback( - (event: ChangeEvent) => { + const importItems = useCallback( + async (result: ImportResult) => { if (!collection) return - if (!event.currentTarget.files?.[0]) return - if (inputOpenedFromImportButton.current) { - form.current?.requestSubmit() - } + + await framer.hideUI() + await importCSV(collection, result) }, [collection] ) - if (result && itemsWithConflict.length > 0) { + // Handle conflicts + if (workflowStep === "manage-conflicts" && result && itemsWithConflict.length > 0) { return ( + // Field mapping step + if (workflowStep === "field-mapping" && collection) { + return ( + { + setWorkflowStep("select-file") + setCsvRecords([]) + setInferredFields([]) + }} + /> + ) + } + + // File selection step + if (workflowStep === "select-file" && collection) { + return (
+ +
+ ) + } -
- - - {isDragging && ( -
-

Drop CSV file to import

-
- )} - - {!isDragging && ( - <> -
-
- -
-
-

Upload CSV

-

- Make sure your collection fields in Framer match the names of your CSV fields. -

-
-
- - - - )} -
+ // Collection selection step + return ( +
+ +
+

Select a collection to import CSV data into.

- +
) } diff --git a/plugins/csv-import/src/FieldMapping.tsx b/plugins/csv-import/src/FieldMapping.tsx new file mode 100644 index 000000000..19a7ccb17 --- /dev/null +++ b/plugins/csv-import/src/FieldMapping.tsx @@ -0,0 +1,235 @@ +import type { Field } from "framer-plugin" +import { framer, useIsAllowedTo } from "framer-plugin" +import { useEffect, useMemo, useState } from "react" +import type { InferredField } from "./typeInference" + +const labelByFieldTypeOption: Record = { + boolean: "Toggle", + date: "Date", + number: "Number", + formattedText: "Formatted Text", + color: "Color", + enum: "Option", + file: "File", + image: "Image", + link: "Link", + string: "Plain Text", + collectionReference: "Reference", + multiCollectionReference: "Multi-Reference", + array: "Gallery", + divider: "Divider", + unsupported: "Unsupported", +} + +interface FieldMappingRowProps { + field: InferredField + ignored: boolean + isAllowedToManage: boolean + onToggleIgnored: (fieldName: string) => void + onNameChange: (fieldName: string, name: string) => void + onFieldTypeChange: (fieldName: string, type: Field["type"]) => void +} + +function FieldMappingRow({ + field, + ignored, + isAllowedToManage, + onToggleIgnored, + onNameChange, + onFieldTypeChange, +}: FieldMappingRowProps) { + const { originalName, name, inferredType, allowedTypes } = field + const disabled = ignored || !isAllowedToManage + + return ( + <> + + + + + + { + onNameChange(originalName, event.target.value) + }} + onKeyDown={event => { + if (event.key === "Enter") { + event.preventDefault() + } + }} + className="field-input" + /> + + ) +} + +interface FieldMappingProps { + inferredFields: InferredField[] + csvRecords: Record[] + onSubmit: (fields: InferredField[], ignoredFieldNames: Set, slugFieldName: string) => Promise + onCancel: () => void +} + +export function FieldMapping({ inferredFields, csvRecords, onSubmit, onCancel }: FieldMappingProps) { + const isAllowedToManage = useIsAllowedTo("Collection.addItems") + + const [fields, setFields] = useState(inferredFields) + const [ignoredFieldNames, setIgnoredFieldNames] = useState>(new Set()) + const [selectedSlugFieldName, setSelectedSlugFieldName] = useState(null) + + // Determine possible slug fields (string or formattedText types) + const possibleSlugFields = useMemo(() => { + return fields.filter(field => field.inferredType === "string" || field.inferredType === "formattedText") + }, [fields]) + + useEffect(() => { + // Auto-select first possible slug field + if (possibleSlugFields.length > 0 && !selectedSlugFieldName) { + setSelectedSlugFieldName(possibleSlugFields[0]?.originalName ?? null) + } + }, [possibleSlugFields, selectedSlugFieldName]) + + const changeFieldName = (originalName: string, name: string) => { + setFields(prevFields => + prevFields.map(field => (field.originalName === originalName ? { ...field, name } : field)) + ) + } + + const changeFieldType = (originalName: string, type: Field["type"]) => { + setFields(prevFields => + prevFields.map(field => + field.originalName === originalName && field.allowedTypes.includes(type) + ? { ...field, inferredType: type } + : field + ) + ) + } + + const toggleFieldIgnoredState = (fieldName: string) => { + setIgnoredFieldNames(prevIgnored => { + const updated = new Set(prevIgnored) + if (updated.has(fieldName)) { + updated.delete(fieldName) + } else { + updated.add(fieldName) + } + return updated + }) + } + + const handleSubmit = async (event: React.FormEvent) => { + event.preventDefault() + + if (!selectedSlugFieldName) { + framer.notify("Please select a slug field before importing.", { variant: "warning" }) + return + } + + await onSubmit(fields, ignoredFieldNames, selectedSlugFieldName) + } + + return ( +
+
+
void handleSubmit(e)}> + + +
+ CSV Column + Type + Name + {fields.map(field => ( + + ))} +
+ +
+
+
+ + +
+
+
+
+ ) +} diff --git a/plugins/csv-import/src/SelectCSVFile.tsx b/plugins/csv-import/src/SelectCSVFile.tsx new file mode 100644 index 000000000..0d2349f88 --- /dev/null +++ b/plugins/csv-import/src/SelectCSVFile.tsx @@ -0,0 +1,160 @@ +import { type ChangeEvent, useCallback, useEffect, useRef, useState } from "react" +import { ImportIcon } from "./ImportIcon" + +interface SelectCSVFileProps { + onFileSelected: (csvContent: string) => Promise +} + +export function SelectCSVFile({ onFileSelected }: SelectCSVFileProps) { + const form = useRef(null) + const inputOpenedFromImportButton = useRef(false) + const [isDragging, setIsDragging] = useState(false) + + useEffect(() => { + const formElement = form.current + if (!formElement) return + + const handleDragOver = (event: DragEvent) => { + event.preventDefault() + setIsDragging(true) + } + + const handleDragLeave = (event: DragEvent) => { + if (!event.relatedTarget) { + setIsDragging(false) + } + } + + const handleDrop = (event: DragEvent) => { + event.preventDefault() + setIsDragging(false) + + const file = event.dataTransfer?.files[0] + if (!file?.name.endsWith(".csv")) return + + const input = document.getElementById("file-input") as HTMLInputElement + const dataTransfer = new DataTransfer() + dataTransfer.items.add(file) + input.files = dataTransfer.files + formElement.requestSubmit() + } + + formElement.addEventListener("dragover", handleDragOver) + formElement.addEventListener("dragleave", handleDragLeave) + formElement.addEventListener("drop", handleDrop) + + return () => { + formElement.removeEventListener("dragover", handleDragOver) + formElement.removeEventListener("dragleave", handleDragLeave) + formElement.removeEventListener("drop", handleDrop) + } + }, []) + + useEffect(() => { + const handlePaste = ({ clipboardData }: ClipboardEvent) => { + if (!clipboardData) return + + const task = async () => { + let csv = "" + + try { + csv = clipboardData.getData("text/plain") + if (!csv) return + } catch (error) { + console.error("Error accessing clipboard data:", error) + return + } + + await onFileSelected(csv) + } + + void task() + } + + window.addEventListener("paste", handlePaste) + + return () => { + window.removeEventListener("paste", handlePaste) + } + }, [onFileSelected]) + + const handleSubmit = useCallback( + (event: React.FormEvent) => { + event.preventDefault() + + if (!form.current) throw new Error("Form ref not set") + + const formData = new FormData(form.current) + const fileValue = formData.get("file") + + if (!fileValue || typeof fileValue === "string") return + + const file = fileValue + + void file.text().then(onFileSelected) + }, + [onFileSelected] + ) + + const handleFileChange = useCallback((event: ChangeEvent) => { + if (!event.currentTarget.files?.[0]) return + if (inputOpenedFromImportButton.current) { + form.current?.requestSubmit() + } + }, []) + + return ( +
+ + + {isDragging && ( +
+

Drop CSV file to import

+
+ )} + + {!isDragging && ( + <> +
+
+ +
+
+

Upload CSV

+

Select a CSV file to import. You'll be able to map fields in the next step.

+
+
+ + + + )} +
+ ) +} diff --git a/plugins/csv-import/src/csv.ts b/plugins/csv-import/src/csv.ts index cef0d16af..4b8d8a086 100644 --- a/plugins/csv-import/src/csv.ts +++ b/plugins/csv-import/src/csv.ts @@ -9,6 +9,7 @@ import { } from "framer-plugin" import * as v from "valibot" +import type { InferredField } from "./typeInference" const CSVRecordSchema = v.record(v.string(), v.string()) @@ -382,6 +383,157 @@ export async function processRecords(collection: Collection, records: CSVRecord[ return result } +/** + * Process CSV records with custom field mapping + * This version maps CSV columns to existing collection fields by name + */ +export async function processRecordsWithFieldMapping( + collection: Collection, + records: CSVRecord[], + inferredFields: InferredField[], + ignoredFieldNames: Set, + slugFieldName: string +): Promise { + if (!collection.slugFieldName) { + throw new ImportError("error", "Import failed. No slug field was found in your CMS Collection.") + } + + const existingItems = await collection.getItems() + + const result: ImportResult = { + warnings: { + missingSlugCount: 0, + doubleSlugCount: 0, + skippedValueCount: 0, + skippedValueKeys: new Set(), + }, + items: [], + } + + // Create field mapping from inferred fields to CSV column names + const csvToFieldMapping = new Map() + for (const field of inferredFields) { + if (!ignoredFieldNames.has(field.originalName)) { + // Map CSV column name to the field name user wants to use + csvToFieldMapping.set(field.originalName, field.name || field.originalName) + } + } + + // Get collection fields + const fields = await collection.getFields() + const allItemIdBySlug = new Map>() + + // Build reference maps for collection reference fields + for (const field of fields) { + if (field.type === "collectionReference" || field.type === "multiCollectionReference") { + const collectionIdBySlug = allItemIdBySlug.get(field.collectionId) ?? new Map() + + const referencedCollection = await framer.getCollection(field.collectionId) + if (!referencedCollection) { + throw new ImportError( + "error", + `Import failed. "${field.name}" references a Collection that doesn't exist.` + ) + } + + const items = await referencedCollection.getItems() + for (const item of items) { + collectionIdBySlug.set(item.slug, item.id) + } + + allItemIdBySlug.set(field.collectionId, collectionIdBySlug) + } + } + + // Check if CSV has a draft column + const firstRecord = records[0] + assert(firstRecord, "No records were found in your CSV.") + const csvHeader = Object.keys(firstRecord) + const hasDraftColumn = csvHeader.includes(":draft") + + const newSlugValues = new Set() + const existingItemsBySlug = new Map() + for (const item of existingItems) { + existingItemsBySlug.set(item.slug, item) + } + + // Find fields to import based on mapping + const fieldsToImport = fields.filter(field => { + // Check if any CSV column maps to this field name + for (const [, mappedName] of csvToFieldMapping) { + if (collator.compare(mappedName, field.name) === 0) { + return true + } + } + return false + }) + + for (const record of records) { + // Get slug value + const slugValue = findRecordValue(record, slugFieldName) + if (!slugValue || slugValue.trim() === "") { + result.warnings.missingSlugCount++ + continue + } + + const slug = slugify(slugValue) + if (newSlugValues.has(slug)) { + result.warnings.doubleSlugCount++ + continue + } + + // Parse draft status + let draft = false + if (hasDraftColumn) { + const draftValue = findRecordValue(record, ":draft") + if (draftValue && draftValue.trim() !== "") { + draft = BOOLEAN_TRUTHY_VALUES.test(draftValue.trim()) + } + } + + const fieldData: FieldDataInput = {} + for (const field of fieldsToImport) { + // Find the CSV column that maps to this field + let csvColumnName: string | undefined + for (const [csvColumn, mappedName] of csvToFieldMapping) { + if (collator.compare(mappedName, field.name) === 0) { + csvColumnName = csvColumn + break + } + } + + if (!csvColumnName) continue + + const value = findRecordValue(record, csvColumnName) + const fieldDataEntry = getFieldDataEntryInputForField(field, value, allItemIdBySlug, record) + + if (fieldDataEntry instanceof ConversionError) { + result.warnings.skippedValueCount++ + result.warnings.skippedValueKeys.add(field.name) + continue + } + + fieldData[field.id] = fieldDataEntry + } + + const item: ImportResultItem = { + id: existingItemsBySlug.get(slug)?.id, + slug, + fieldData, + action: existingItemsBySlug.get(slug) ? "conflict" : "add", + draft, + } + + if (item.action === "add") { + newSlugValues.add(slug) + } + + result.items.push(item) + } + + return result +} + export async function importCSV(collection: Collection, result: ImportResult) { const totalItems = result.items.length const totalAdded = result.items.filter(item => item.action === "add").length diff --git a/plugins/csv-import/src/typeInference.ts b/plugins/csv-import/src/typeInference.ts new file mode 100644 index 000000000..b56b1d6b6 --- /dev/null +++ b/plugins/csv-import/src/typeInference.ts @@ -0,0 +1,159 @@ +import type { Field } from "framer-plugin" + +export interface InferredField { + name: string + originalName: string + inferredType: Field["type"] + allowedTypes: Field["type"][] +} + +const BOOLEAN_TRUTHY_VALUES = /^(1|y(?:es)?|true)$/iu +const BOOLEAN_FALSY_VALUES = /^(0|n(?:o)?|false)$/iu +const URL_PATTERN = /^https?:\/\/.+/i +const COLOR_PATTERN = /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i +const IMAGE_URL_PATTERN = /^https?:\/\/.+\.(jpg|jpeg|png|gif|webp|svg)$/i + +/** + * Infer the field type from CSV data + */ +export function inferFieldType(values: (string | null)[]): Field["type"] { + const nonNullValues = values.filter((v): v is string => v !== null && v.trim() !== "") + + if (nonNullValues.length === 0) { + return "string" + } + + // Check if all values are booleans + const allBoolean = nonNullValues.every(v => BOOLEAN_TRUTHY_VALUES.test(v) || BOOLEAN_FALSY_VALUES.test(v)) + if (allBoolean) { + return "boolean" + } + + // Check if all values are numbers + const allNumbers = nonNullValues.every(v => { + const num = Number(v) + return !Number.isNaN(num) && v.trim() !== "" + }) + if (allNumbers) { + return "number" + } + + // Check if all values are valid dates + const allDates = nonNullValues.every(v => { + const date = new Date(v) + return !Number.isNaN(date.getTime()) + }) + if (allDates && nonNullValues.length > 0) { + // Additional check: ensure it looks like a date string + const hasDateLikeFormat = nonNullValues.some( + v => + /\d{4}-\d{2}-\d{2}/.test(v) || // ISO format + /\d{1,2}\/\d{1,2}\/\d{2,4}/.test(v) || // Common date formats + /\d{1,2}-\d{1,2}-\d{2,4}/.test(v) + ) + if (hasDateLikeFormat) { + return "date" + } + } + + // Check if all values are colors + const allColors = nonNullValues.every(v => COLOR_PATTERN.test(v.trim())) + if (allColors) { + return "color" + } + + // Check if all values are image URLs + const allImageUrls = nonNullValues.every(v => IMAGE_URL_PATTERN.test(v.trim())) + if (allImageUrls) { + return "image" + } + + // Check if all values are URLs + const allUrls = nonNullValues.every(v => URL_PATTERN.test(v.trim())) + if (allUrls) { + return "link" + } + + // Check if values contain HTML or markdown (formatted text) + const hasFormatting = nonNullValues.some( + v => + /<[^>]+>/.test(v) || // HTML tags + /\*\*.*\*\*/.test(v) || // Bold markdown + /\*.*\*/.test(v) || // Italic markdown + /\[.*\]\(.*\)/.test(v) // Markdown links + ) + if (hasFormatting) { + return "formattedText" + } + + // Default to string + return "string" +} + +/** + * Get allowed types for a field based on its inferred type + */ +export function getAllowedTypes(inferredType: Field["type"]): Field["type"][] { + // Define which types can be converted to which other types + const typeCompatibility: Record = { + string: ["string", "formattedText", "link", "color", "file", "image"], + formattedText: ["formattedText", "string"], + number: ["number", "string"], + boolean: ["boolean", "string"], + date: ["date", "string"], + color: ["color", "string"], + link: ["link", "string"], + image: ["image", "file", "link", "string"], + file: ["file", "link", "string"], + enum: ["enum", "string"], + collectionReference: ["collectionReference"], + multiCollectionReference: ["multiCollectionReference"], + array: ["array"], + divider: ["divider"], + unsupported: ["unsupported"], + } + + return typeCompatibility[inferredType] +} + +/** + * Infer field types from CSV records + */ +export function inferFieldsFromCSV(records: Record[]): InferredField[] { + if (records.length === 0) { + return [] + } + + const firstRecord = records[0] + if (!firstRecord) { + return [] + } + + const fieldNames = Object.keys(firstRecord) + const inferredFields: InferredField[] = [] + + for (const fieldName of fieldNames) { + // Skip special fields + if (fieldName.startsWith(":")) { + continue + } + + // Collect all values for this field + const values = records.map(record => { + const value = record[fieldName] + return value && value.trim() !== "" ? value : null + }) + + const inferredType = inferFieldType(values) + const allowedTypes = getAllowedTypes(inferredType) + + inferredFields.push({ + name: fieldName, + originalName: fieldName, + inferredType, + allowedTypes, + }) + } + + return inferredFields +} From ad60413c16ea4bf798c3b383b04b504386373962 Mon Sep 17 00:00:00 2001 From: "nick.lucas" Date: Mon, 15 Dec 2025 15:43:59 +0000 Subject: [PATCH 02/36] Add basic minirouter --- plugins/csv-import/src/App.tsx | 2 + plugins/csv-import/src/main.tsx | 5 +- plugins/csv-import/src/minirouter.tsx | 66 +++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 plugins/csv-import/src/minirouter.tsx diff --git a/plugins/csv-import/src/App.tsx b/plugins/csv-import/src/App.tsx index 02a107a27..e0693d404 100644 --- a/plugins/csv-import/src/App.tsx +++ b/plugins/csv-import/src/App.tsx @@ -10,6 +10,7 @@ import { ManageConflicts } from "./ManageConflicts" import { SelectCSVFile } from "./SelectCSVFile" import type { InferredField } from "./typeInference" import { inferFieldsFromCSV } from "./typeInference" +import { useMiniRouter } from "./minirouter" type WorkflowStep = "select-collection" | "select-file" | "field-mapping" | "manage-conflicts" @@ -17,6 +18,7 @@ export function App({ initialCollection }: { initialCollection: Collection | nul const [collection, setCollection] = useState(initialCollection) const isAllowedToAddItems = useIsAllowedTo("Collection.addItems") + const router = useMiniRouter() const [workflowStep, setWorkflowStep] = useState( initialCollection ? "select-file" : "select-collection" ) diff --git a/plugins/csv-import/src/main.tsx b/plugins/csv-import/src/main.tsx index 7cebef349..a83493dff 100644 --- a/plugins/csv-import/src/main.tsx +++ b/plugins/csv-import/src/main.tsx @@ -4,6 +4,7 @@ import { framer } from "framer-plugin" import React from "react" import ReactDOM from "react-dom/client" import { App } from "./App.tsx" +import { MiniRouterProvider } from "./minirouter.tsx" const root = document.getElementById("root") if (!root) throw new Error("Root element not found") @@ -15,6 +16,8 @@ if (collection && collection.managedBy !== "user") { ReactDOM.createRoot(root).render( - + + + ) diff --git a/plugins/csv-import/src/minirouter.tsx b/plugins/csv-import/src/minirouter.tsx new file mode 100644 index 000000000..7eb29ebe6 --- /dev/null +++ b/plugins/csv-import/src/minirouter.tsx @@ -0,0 +1,66 @@ +import { framer, type UIOptions } from "framer-plugin" +import { createContext, useContext, useMemo, useState, type ReactNode } from "react" + +type Route = + | { + uid: "home" + opts: undefined + } + | { + uid: "select-file" + opts: undefined + } + | { + uid: "field-mapping" + opts: undefined + } + | { + uid: "manage-conflicts" + opts: undefined + } + +const fallbackUiOptions: UIOptions = { width: 260, height: 330, resizable: false } +const defaultUiOptions = { + home: fallbackUiOptions, + "field-mapping": { width: 400, height: 600, resizable: true }, + "manage-conflicts": { width: 260, height: 165, resizable: false }, +} as Record + +interface MiniRouterContextType { + // Define your context properties here + currentRoute: Route + navigate: (route: Route) => Promise +} + +const MiniRouterContext = createContext(undefined) + +interface MiniRouterProviderProps { + children: ReactNode +} + +export function MiniRouterProvider({ children }: MiniRouterProviderProps) { + const [currentRoute, setCurrentRoute] = useState({ uid: "home", opts: undefined }) + + const value: MiniRouterContextType = useMemo(() => { + return { + currentRoute, + navigate: async route => { + const uiOptions = defaultUiOptions[route.uid] ?? fallbackUiOptions + await framer.showUI(uiOptions) + + setCurrentRoute(route) + }, + } + }, [currentRoute]) + + return {children} +} + +// eslint-disable-next-line react-refresh/only-export-components +export const useMiniRouter = () => { + const context = useContext(MiniRouterContext) + if (context === undefined) { + throw new Error("useMiniRouter must be used within a MiniRouterProvider") + } + return context +} From 75d89ea52e8b8fa64ce8dfb73b4c2d372b7503d3 Mon Sep 17 00:00:00 2001 From: "nick.lucas" Date: Tue, 16 Dec 2025 10:45:13 +0000 Subject: [PATCH 03/36] Restyle file dropper --- plugins/csv-import/src/App.css | 47 ++++++++++-------------- plugins/csv-import/src/App.tsx | 2 +- plugins/csv-import/src/SelectCSVFile.tsx | 6 +-- 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/plugins/csv-import/src/App.css b/plugins/csv-import/src/App.css index 83c343da1..d4b23b90b 100644 --- a/plugins/csv-import/src/App.css +++ b/plugins/csv-import/src/App.css @@ -48,32 +48,6 @@ /* Main screen */ -.dropzone { - position: relative; - display: flex; - flex: 1; - flex-direction: column; - align-items: center; - justify-content: center; - margin: 0; - width: 100%; - min-height: 170px; - border-radius: 8px; - background-color: color-mix(in srgb, var(--framer-color-tint) 10%, transparent); - line-height: 1; - transition: all 0.2s ease; - border: 1px dashed transparent; -} - -.dropzone.dragging { - border-color: var(--framer-color-tint); -} - -.dropzone p { - color: var(--framer-color-tint); - font-weight: 600; -} - .file-input { visibility: hidden; position: absolute; @@ -103,8 +77,14 @@ width: 100%; flex: 1; text-align: center; - max-width: 160px; gap: 15px; + + padding: 20px; + margin: 10px; + aspect-ratio: 1 / 1; + border: 2px dashed rgba(255, 255, 255, 0.2); + border-radius: 12px; + background-color: rgba(255, 255, 255, 0.05); } .intro h2 { @@ -119,6 +99,19 @@ color: var(--framer-color-text-tertiary); } +.dropzone { + border-color: var(--framer-color-tint); +} + +.dropzone p { + color: var(--framer-color-tint); + font-weight: 600; +} + +.no-border { + border: none; +} + .collection-selector { display: flex; gap: 8px; diff --git a/plugins/csv-import/src/App.tsx b/plugins/csv-import/src/App.tsx index e0693d404..38ba82600 100644 --- a/plugins/csv-import/src/App.tsx +++ b/plugins/csv-import/src/App.tsx @@ -194,7 +194,7 @@ export function App({ initialCollection }: { initialCollection: Collection | nul return (
-
+

Select a collection to import CSV data into.

diff --git a/plugins/csv-import/src/SelectCSVFile.tsx b/plugins/csv-import/src/SelectCSVFile.tsx index 0d2349f88..388cbc827 100644 --- a/plugins/csv-import/src/SelectCSVFile.tsx +++ b/plugins/csv-import/src/SelectCSVFile.tsx @@ -20,7 +20,7 @@ export function SelectCSVFile({ onFileSelected }: SelectCSVFileProps) { } const handleDragLeave = (event: DragEvent) => { - if (!event.relatedTarget) { + if (event.relatedTarget) { setIsDragging(false) } } @@ -124,7 +124,7 @@ export function SelectCSVFile({ onFileSelected }: SelectCSVFileProps) { /> {isDragging && ( -
+

Drop CSV file to import

)} @@ -137,7 +137,7 @@ export function SelectCSVFile({ onFileSelected }: SelectCSVFileProps) {

Upload CSV

-

Select a CSV file to import. You'll be able to map fields in the next step.

+

Select a CSV file to import, paste CSV data, or drag and drop a CSV file.

From c2cbfcdabb7a8597165a47650cdc9dc2f6e8f0d6 Mon Sep 17 00:00:00 2001 From: "nick.lucas" Date: Tue, 16 Dec 2025 10:50:29 +0000 Subject: [PATCH 04/36] Improve mouse leave handling --- plugins/csv-import/src/SelectCSVFile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/csv-import/src/SelectCSVFile.tsx b/plugins/csv-import/src/SelectCSVFile.tsx index 388cbc827..7a1df4d4f 100644 --- a/plugins/csv-import/src/SelectCSVFile.tsx +++ b/plugins/csv-import/src/SelectCSVFile.tsx @@ -20,7 +20,7 @@ export function SelectCSVFile({ onFileSelected }: SelectCSVFileProps) { } const handleDragLeave = (event: DragEvent) => { - if (event.relatedTarget) { + if (!formElement.contains(event.relatedTarget as Node)) { setIsDragging(false) } } From 89b8f33da1afd7236ca2d542e22b4e178af16731 Mon Sep 17 00:00:00 2001 From: "nick.lucas" Date: Tue, 16 Dec 2025 12:02:04 +0000 Subject: [PATCH 05/36] Upgrade framer plugin in csv import --- ...r-plugin-npm-3.9.0-37940aa6dc-2d8249cc82.zip | Bin 0 -> 61662 bytes ...n-npm-3.9.0-beta.1-d4f15f8a6a-1f58b75683.zip | Bin 61724 -> 0 bytes plugins/csv-import/package.json | 2 +- yarn.lock | 10 +++++----- 4 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 .yarn/cache/framer-plugin-npm-3.9.0-37940aa6dc-2d8249cc82.zip delete mode 100644 .yarn/cache/framer-plugin-npm-3.9.0-beta.1-d4f15f8a6a-1f58b75683.zip diff --git a/.yarn/cache/framer-plugin-npm-3.9.0-37940aa6dc-2d8249cc82.zip b/.yarn/cache/framer-plugin-npm-3.9.0-37940aa6dc-2d8249cc82.zip new file mode 100644 index 0000000000000000000000000000000000000000..c25e796cae7a0cfc4f4df2dd8421af7a5b74a6a5 GIT binary patch literal 61662 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∈g^qrC0vVb>>sB1+4~_C6CyuFv04nB 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 G?f(Egxoy+{ literal 0 HcmV?d00001 diff --git a/.yarn/cache/framer-plugin-npm-3.9.0-beta.1-d4f15f8a6a-1f58b75683.zip b/.yarn/cache/framer-plugin-npm-3.9.0-beta.1-d4f15f8a6a-1f58b75683.zip deleted file mode 100644 index a513f930cf81116d77f326b10b3e268a70a2a486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61724 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 Qmp|L=pU=T|`Pb3^0g8SGCjbBd diff --git a/plugins/csv-import/package.json b/plugins/csv-import/package.json index ec0406eb4..383d1feb9 100644 --- a/plugins/csv-import/package.json +++ b/plugins/csv-import/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "csv-parse": "^6.1.0", - "framer-plugin": "3.9.0-beta.1", + "framer-plugin": "3.9.0", "react": "^18.3.1", "react-dom": "^18.3.1", "valibot": "^1.2.0" diff --git a/yarn.lock b/yarn.lock index f959f91a1..2ae00aec5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3713,7 +3713,7 @@ __metadata: "@types/react": "npm:^18.3.24" "@types/react-dom": "npm:^18.3.7" csv-parse: "npm:^6.1.0" - framer-plugin: "npm:3.9.0-beta.1" + framer-plugin: "npm:3.9.0" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" valibot: "npm:^1.2.0" @@ -4593,13 +4593,13 @@ __metadata: languageName: node linkType: hard -"framer-plugin@npm:3.9.0-beta.1": - version: 3.9.0-beta.1 - resolution: "framer-plugin@npm:3.9.0-beta.1" +"framer-plugin@npm:3.9.0": + version: 3.9.0 + resolution: "framer-plugin@npm:3.9.0" peerDependencies: react: ^18.2.0 react-dom: ^18.2.0 - checksum: 10/1f58b75683d5cfedb812422916bcf6e4a63c6141b3f0df49eb13551894929edecabe8cb9ebbcb0b5d693efb277412e08e32b7652c41bea58f14b8bd0949106fe + checksum: 10/2d8249cc82faadd57880e3fec97db7b3ed7aba5b8e80beb6c250ddf773e0d09265dc0990569bc898b193b790320b7ae89a71fa981c269ff685a3c465f8520713 languageName: node linkType: hard From 57cdef071f46d9fe95e2e16cfbe552d2a428a980 Mon Sep 17 00:00:00 2001 From: "nick.lucas" Date: Tue, 16 Dec 2025 14:11:19 +0000 Subject: [PATCH 06/36] Move button inside drop zone for clarity --- plugins/csv-import/src/App.css | 13 +++++++++++- plugins/csv-import/src/SelectCSVFile.tsx | 26 ++++++++++++------------ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/plugins/csv-import/src/App.css b/plugins/csv-import/src/App.css index d4b23b90b..b6c21c232 100644 --- a/plugins/csv-import/src/App.css +++ b/plugins/csv-import/src/App.css @@ -1,4 +1,3 @@ -.import-collection, .manage-conflicts { display: flex; flex-direction: column; @@ -9,6 +8,12 @@ } .import-collection { + display: flex; + flex-direction: column; + justify-content: space-between; + text-align: left; + height: 100%; + padding: 0 15px 5px 15px; align-items: center; } @@ -99,6 +104,12 @@ color: var(--framer-color-text-tertiary); } +.intro .content { + display: flex; + flex-direction: column; + flex: 1 1 auto; +} + .dropzone { border-color: var(--framer-color-tint); } diff --git a/plugins/csv-import/src/SelectCSVFile.tsx b/plugins/csv-import/src/SelectCSVFile.tsx index 7a1df4d4f..e844877d2 100644 --- a/plugins/csv-import/src/SelectCSVFile.tsx +++ b/plugins/csv-import/src/SelectCSVFile.tsx @@ -139,20 +139,20 @@ export function SelectCSVFile({ onFileSelected }: SelectCSVFileProps) {

Upload CSV

Select a CSV file to import, paste CSV data, or drag and drop a CSV file.

- - + + )} From 824d04cfc6d0f4b0bd6db004090e8a6bff134b95 Mon Sep 17 00:00:00 2001 From: "nick.lucas" Date: Tue, 16 Dec 2025 14:14:56 +0000 Subject: [PATCH 07/36] Fix biome --- plugins/csv-import/src/App.tsx | 2 +- plugins/csv-import/src/minirouter.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/csv-import/src/App.tsx b/plugins/csv-import/src/App.tsx index 38ba82600..d915fee87 100644 --- a/plugins/csv-import/src/App.tsx +++ b/plugins/csv-import/src/App.tsx @@ -7,10 +7,10 @@ import { CollectionSelector } from "./CollectionSelector" import { ImportError, importCSV, parseCSV, processRecordsWithFieldMapping } from "./csv" import { FieldMapping } from "./FieldMapping" import { ManageConflicts } from "./ManageConflicts" +import { useMiniRouter } from "./minirouter" import { SelectCSVFile } from "./SelectCSVFile" import type { InferredField } from "./typeInference" import { inferFieldsFromCSV } from "./typeInference" -import { useMiniRouter } from "./minirouter" type WorkflowStep = "select-collection" | "select-file" | "field-mapping" | "manage-conflicts" diff --git a/plugins/csv-import/src/minirouter.tsx b/plugins/csv-import/src/minirouter.tsx index 7eb29ebe6..7d27329b4 100644 --- a/plugins/csv-import/src/minirouter.tsx +++ b/plugins/csv-import/src/minirouter.tsx @@ -1,5 +1,5 @@ import { framer, type UIOptions } from "framer-plugin" -import { createContext, useContext, useMemo, useState, type ReactNode } from "react" +import { createContext, type ReactNode, useContext, useMemo, useState } from "react" type Route = | { From 315f950fef8ead569a8dff1b93fa1e34dac53f32 Mon Sep 17 00:00:00 2001 From: "nick.lucas" Date: Tue, 16 Dec 2025 14:58:41 +0000 Subject: [PATCH 08/36] Implement minirouter --- plugins/csv-import/src/App.tsx | 190 ++++++++++-------------- plugins/csv-import/src/FieldMapping.tsx | 4 +- plugins/csv-import/src/minirouter.tsx | 37 +++-- 3 files changed, 102 insertions(+), 129 deletions(-) diff --git a/plugins/csv-import/src/App.tsx b/plugins/csv-import/src/App.tsx index d915fee87..cd367353e 100644 --- a/plugins/csv-import/src/App.tsx +++ b/plugins/csv-import/src/App.tsx @@ -1,6 +1,6 @@ import type { Collection } from "framer-plugin" import { FramerPluginClosedError, framer, useIsAllowedTo } from "framer-plugin" -import { useCallback, useEffect, useMemo, useState } from "react" +import { useCallback, useState } from "react" import type { ImportResult } from "./csv" import "./App.css" import { CollectionSelector } from "./CollectionSelector" @@ -12,58 +12,11 @@ import { SelectCSVFile } from "./SelectCSVFile" import type { InferredField } from "./typeInference" import { inferFieldsFromCSV } from "./typeInference" -type WorkflowStep = "select-collection" | "select-file" | "field-mapping" | "manage-conflicts" - export function App({ initialCollection }: { initialCollection: Collection | null }) { const [collection, setCollection] = useState(initialCollection) const isAllowedToAddItems = useIsAllowedTo("Collection.addItems") - const router = useMiniRouter() - const [workflowStep, setWorkflowStep] = useState( - initialCollection ? "select-file" : "select-collection" - ) - const [csvRecords, setCsvRecords] = useState[]>([]) - const [inferredFields, setInferredFields] = useState([]) - const [result, setResult] = useState(null) - - const itemsWithConflict = useMemo(() => result?.items.filter(item => item.action === "conflict") ?? [], [result]) - - useEffect(() => { - // Adjust UI size based on workflow step - if (workflowStep === "field-mapping") { - void framer.showUI({ - width: 400, - height: 600, - resizable: true, - }) - } else if (workflowStep === "manage-conflicts") { - void framer.showUI({ - width: 260, - height: 165, - resizable: false, - }) - } else { - void framer.showUI({ - width: 260, - height: 330, - resizable: false, - }) - } - }, [workflowStep]) - - useEffect(() => { - // Update workflow step based on collection selection - if (collection && workflowStep === "select-collection") { - setWorkflowStep("select-file") - } - }, [collection, workflowStep]) - - useEffect(() => { - // Update workflow step when conflicts are detected - if (itemsWithConflict.length > 0 && workflowStep !== "manage-conflicts") { - setWorkflowStep("manage-conflicts") - } - }, [itemsWithConflict, workflowStep]) + const { currentRoute, navigate } = useMiniRouter() const handleFileSelected = useCallback( async (csvContent: string) => { @@ -79,9 +32,7 @@ export function App({ initialCollection }: { initialCollection: Collection | nul // Infer field types from CSV data const fields = inferFieldsFromCSV(records) - setCsvRecords(records) - setInferredFields(fields) - setWorkflowStep("field-mapping") + await navigate({ uid: "field-mapping", opts: { csvRecords: records, inferredFields: fields } }) } catch (error) { if (error instanceof FramerPluginClosedError) throw error @@ -97,30 +48,38 @@ export function App({ initialCollection }: { initialCollection: Collection | nul }) } }, - [collection, isAllowedToAddItems] + [collection, isAllowedToAddItems, navigate] ) const handleFieldMappingSubmit = useCallback( - async (fields: InferredField[], ignoredFieldNames: Set, slugFieldName: string) => { + async (opts: { + csvRecords: Record[] + fields: InferredField[] + ignoredFieldNames: Set + slugFieldName: string + }) => { if (!collection) return if (!isAllowedToAddItems) return try { const result = await processRecordsWithFieldMapping( collection, - csvRecords, - fields, - ignoredFieldNames, - slugFieldName + opts.csvRecords, + opts.fields, + opts.ignoredFieldNames, + opts.slugFieldName ) - setResult(result) - if (result.items.some(item => item.action === "conflict")) { + const itemsWithConflict = result.items.filter(item => item.action === "conflict") + if (itemsWithConflict.length > 0) { + await navigate({ uid: "manage-conflicts", opts: { conflicts: itemsWithConflict, result } }) + return - } + } else { + await importCSV(collection, result) - await framer.hideUI() - await importCSV(collection, result) + await framer.hideUI() + } } catch (error) { if (error instanceof FramerPluginClosedError) throw error @@ -136,7 +95,7 @@ export function App({ initialCollection }: { initialCollection: Collection | nul }) } }, - [collection, csvRecords, isAllowedToAddItems] + [collection, isAllowedToAddItems, navigate] ) const importItems = useCallback( @@ -149,54 +108,59 @@ export function App({ initialCollection }: { initialCollection: Collection | nul [collection] ) - // Handle conflicts - if (workflowStep === "manage-conflicts" && result && itemsWithConflict.length > 0) { - return ( - { - const updatedItems = result.items.map( - item => resolvedItems.find(resolved => resolved.slug === item.slug) ?? item - ) - void importItems({ ...result, items: updatedItems }) - }} - /> - ) - } - - // Field mapping step - if (workflowStep === "field-mapping" && collection) { - return ( - { - setWorkflowStep("select-file") - setCsvRecords([]) - setInferredFields([]) - }} - /> - ) - } - - // File selection step - if (workflowStep === "select-file" && collection) { - return ( -
- - -
- ) + switch (currentRoute.uid) { + case "home": { + if (collection) { + return ( +
+ + +
+ ) + } else { + return ( +
+ +
+

Select a collection to import CSV data into.

+
+
+ ) + } + } + case "manage-conflicts": { + return ( + { + const updatedItems = currentRoute.opts.result.items.map( + item => resolvedItems.find(resolved => resolved.slug === item.slug) ?? item + ) + void importItems({ ...currentRoute.opts.result, items: updatedItems }) + }} + /> + ) + } + case "field-mapping": + return ( + + handleFieldMappingSubmit({ + csvRecords: currentRoute.opts.csvRecords, + fields, + ignoredFieldNames, + slugFieldName, + }) + } + onCancel={async () => { + await navigate({ uid: "home", opts: undefined }) + }} + /> + ) + default: + // @ts-expect-error -- exhaustive switch + return
Unknown route {currentRoute.uid}
} - - // Collection selection step - return ( -
- -
-

Select a collection to import CSV data into.

-
-
- ) } diff --git a/plugins/csv-import/src/FieldMapping.tsx b/plugins/csv-import/src/FieldMapping.tsx index 19a7ccb17..9a5827e1d 100644 --- a/plugins/csv-import/src/FieldMapping.tsx +++ b/plugins/csv-import/src/FieldMapping.tsx @@ -111,7 +111,7 @@ interface FieldMappingProps { inferredFields: InferredField[] csvRecords: Record[] onSubmit: (fields: InferredField[], ignoredFieldNames: Set, slugFieldName: string) => Promise - onCancel: () => void + onCancel: () => Promise } export function FieldMapping({ inferredFields, csvRecords, onSubmit, onCancel }: FieldMappingProps) { @@ -216,7 +216,7 @@ export function FieldMapping({ inferredFields, csvRecords, onSubmit, onCancel }: