mirror of
https://github.com/rowyio/rowy.git
synced 2026-09-01 19:50:46 +02:00
added Airtable import/upload files
This commit is contained in:
@@ -28,6 +28,8 @@ import { fieldParser } from "@src/components/TableModals/ImportAirtableWizard/ut
|
||||
import Step1Columns from "./Step1Columns";
|
||||
import Step2NewColumns from "./Step2NewColumns";
|
||||
import Step3Preview from "./Step3Preview";
|
||||
import useConverter from "@src/components/TableModals/ImportCsvWizard/useConverter";
|
||||
import useUploadFileFromURL from "@src/components/TableModals/ImportCsvWizard/useUploadFileFromURL";
|
||||
|
||||
export type AirtableConfig = {
|
||||
pairs: { fieldKey: string; columnKey: string }[];
|
||||
@@ -65,6 +67,8 @@ export default function ImportAirtableWizard({ onClose }: ITableModalProps) {
|
||||
newColumns: [],
|
||||
documentId: "recordId",
|
||||
});
|
||||
const { needsUploadTypes, getConverter } = useConverter();
|
||||
const { addTask, runBatchedUpload, hasUploadJobs } = useUploadFileFromURL();
|
||||
|
||||
const updateConfig: IStepProps["updateConfig"] = useCallback((value) => {
|
||||
setConfig((prev) => {
|
||||
@@ -99,10 +103,24 @@ export default function ImportAirtableWizard({ onClose }: ITableModalProps) {
|
||||
const matchingColumn =
|
||||
columns[pair.columnKey] ??
|
||||
find(config.newColumns, { key: pair.columnKey });
|
||||
const parser = fieldParser(matchingColumn.type);
|
||||
const parser =
|
||||
getConverter(matchingColumn.type) || fieldParser(matchingColumn.type);
|
||||
const value = parser
|
||||
? parser(record.fields[pair.fieldKey])
|
||||
: record.fields[pair.fieldKey];
|
||||
|
||||
if (needsUploadTypes(matchingColumn.type)) {
|
||||
if (value && value.length > 0) {
|
||||
addTask({
|
||||
docRef: {
|
||||
path: `${tableSettings.collection}/${record.id}`,
|
||||
id: record.id,
|
||||
},
|
||||
fieldName: pair.columnKey,
|
||||
files: value,
|
||||
});
|
||||
}
|
||||
}
|
||||
return config.documentId === "recordId"
|
||||
? { ...a, [pair.columnKey]: value, _rowy_ref: { id: record.id } }
|
||||
: { ...a, [pair.columnKey]: value };
|
||||
@@ -196,6 +214,10 @@ export default function ImportAirtableWizard({ onClose }: ITableModalProps) {
|
||||
`Imported ${Number(countRef.current).toLocaleString()} rows`,
|
||||
{ variant: "success" }
|
||||
);
|
||||
|
||||
if (hasUploadJobs()) {
|
||||
await runBatchedUpload();
|
||||
}
|
||||
} catch (e) {
|
||||
enqueueSnackbar((e as Error).message, { variant: "error" });
|
||||
} finally {
|
||||
|
||||
@@ -37,7 +37,6 @@ import {
|
||||
import { ColumnConfig } from "@src/types/table";
|
||||
import { getFieldProp } from "@src/components/fields";
|
||||
import { analytics, logEvent } from "@src/analytics";
|
||||
import { FieldType } from "@src/constants/fields";
|
||||
import { generateId } from "@src/utils/table";
|
||||
import { isValidDocId } from "./utils";
|
||||
import useUploadFileFromURL from "./useUploadFileFromURL";
|
||||
@@ -50,8 +49,6 @@ export type CsvConfig = {
|
||||
documentIdCsvKey: string | null;
|
||||
};
|
||||
|
||||
const needsUploadTypes = [FieldType.image, FieldType.file];
|
||||
|
||||
export interface IStepProps {
|
||||
csvData: NonNullable<ImportCsvData>;
|
||||
config: CsvConfig;
|
||||
@@ -71,8 +68,8 @@ export default function ImportCsvWizard({ onClose }: ITableModalProps) {
|
||||
const theme = useTheme();
|
||||
const isXs = useMediaQuery(theme.breakpoints.down("sm"));
|
||||
const snackbarProgressRef = useRef<ISnackbarProgressRef>();
|
||||
const { addTask, runBatchUpload, askPermission } = useUploadFileFromURL();
|
||||
const { needsConverter, getConverter } = useConverter();
|
||||
const { addTask, runBatchedUpload } = useUploadFileFromURL();
|
||||
const { needsUploadTypes, needsConverter, getConverter } = useConverter();
|
||||
|
||||
const columns = useMemoValue(tableSchema.columns ?? {}, isEqual);
|
||||
|
||||
@@ -147,7 +144,7 @@ export default function ImportCsvWizard({ onClose }: ITableModalProps) {
|
||||
if (needsConverter(column.type)) {
|
||||
requiredConverts[index] = getConverter(column.type);
|
||||
// console.log({ needsUploadTypes }, column.type);
|
||||
if (needsUploadTypes.includes(column.type)) {
|
||||
if (needsUploadTypes(column.type)) {
|
||||
requiredUploads[column.fieldName + ""] = true;
|
||||
}
|
||||
}
|
||||
@@ -158,6 +155,7 @@ export default function ImportCsvWizard({ onClose }: ITableModalProps) {
|
||||
config.pairs,
|
||||
getConverter,
|
||||
needsConverter,
|
||||
needsUploadTypes,
|
||||
tableSchema.columns,
|
||||
]);
|
||||
|
||||
@@ -266,8 +264,8 @@ export default function ImportCsvWizard({ onClose }: ITableModalProps) {
|
||||
`Imported ${Number(validRows.length).toLocaleString()} rows`,
|
||||
{ variant: "success" }
|
||||
);
|
||||
if (Object.keys(requiredUploads).length && (await askPermission())) {
|
||||
await runBatchUpload();
|
||||
if (Object.keys(requiredUploads).length > 0) {
|
||||
await runBatchedUpload();
|
||||
}
|
||||
} catch (e) {
|
||||
enqueueSnackbar((e as Error).message, { variant: "error" });
|
||||
|
||||
@@ -16,6 +16,9 @@ const needsConverter = (type: FieldType) =>
|
||||
FieldType.geoPoint,
|
||||
].includes(type);
|
||||
|
||||
const needsUploadTypes = (type: FieldType) =>
|
||||
[FieldType.image, FieldType.file].includes(type);
|
||||
|
||||
export default function useConverter() {
|
||||
const [firebaseDb] = useAtom(firebaseDbAtom, projectScope);
|
||||
|
||||
@@ -35,27 +38,59 @@ export default function useConverter() {
|
||||
};
|
||||
|
||||
const imageOrFileConverter = (urls: any): RowyFile[] => {
|
||||
if (!urls) return [];
|
||||
if (Array.isArray(urls)) return urls;
|
||||
if (typeof urls === "string") {
|
||||
return urls
|
||||
.split(",")
|
||||
.map((url) => {
|
||||
url = url.trim();
|
||||
if (url !== "") {
|
||||
return {
|
||||
downloadURL: url,
|
||||
name: url.split("/").pop() || "",
|
||||
lastModifiedTS: +new Date(),
|
||||
type: "",
|
||||
};
|
||||
}
|
||||
try {
|
||||
if (!urls) return [];
|
||||
if (Array.isArray(urls)) {
|
||||
return urls
|
||||
.map((url) => {
|
||||
if (typeof url === "string") {
|
||||
url = url.trim();
|
||||
if (url !== "") {
|
||||
return {
|
||||
downloadURL: url,
|
||||
name: url.split("/").pop() || "",
|
||||
lastModifiedTS: +new Date(),
|
||||
type: "",
|
||||
};
|
||||
}
|
||||
} else if (url && typeof url === "object" && url.downloadURL) {
|
||||
return url;
|
||||
} else {
|
||||
if (url.url) {
|
||||
return {
|
||||
downloadURL: url.url,
|
||||
name: url.filename || url.url.split("/").pop() || "",
|
||||
lastModifiedTS: +new Date(),
|
||||
type: "",
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter((val) => val !== null) as RowyFile[];
|
||||
}
|
||||
if (typeof urls === "string") {
|
||||
return urls
|
||||
.split(",")
|
||||
.map((url) => {
|
||||
url = url.trim();
|
||||
if (url !== "") {
|
||||
return {
|
||||
downloadURL: url,
|
||||
name: url.split("/").pop() || "",
|
||||
lastModifiedTS: +new Date(),
|
||||
type: "",
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
.filter((val) => val !== null) as RowyFile[];
|
||||
return null;
|
||||
})
|
||||
.filter((val) => val !== null) as RowyFile[];
|
||||
}
|
||||
return [];
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
const geoPointConverter = (value: any) => {
|
||||
@@ -120,5 +155,6 @@ export default function useConverter() {
|
||||
imageOrFileConverter,
|
||||
getConverter,
|
||||
checkAndConvert,
|
||||
needsUploadTypes,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ export default function useUploadFileFromURL() {
|
||||
[enqueueSnackbar]
|
||||
);
|
||||
|
||||
const runBatchUpload = useCallback(async () => {
|
||||
const runBatchedUpload = useCallback(async () => {
|
||||
if (!snackbarProgressId.current) {
|
||||
showProgress(jobs.current.length);
|
||||
}
|
||||
@@ -145,7 +145,7 @@ export default function useUploadFileFromURL() {
|
||||
await batchUpload(currentJobs);
|
||||
|
||||
if (jobs.current.length > 0) {
|
||||
await runBatchUpload();
|
||||
await runBatchedUpload();
|
||||
}
|
||||
|
||||
if (snackbarProgressId.current) {
|
||||
@@ -157,10 +157,12 @@ export default function useUploadFileFromURL() {
|
||||
jobs.current.push(job);
|
||||
}, []);
|
||||
|
||||
const hasUploadJobs = () => jobs.current.length > 0;
|
||||
return {
|
||||
addTask,
|
||||
runBatchUpload,
|
||||
runBatchedUpload,
|
||||
askPermission,
|
||||
hasUploadJobs,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user