-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add plugin-copy-column #611
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,141 @@ | ||||||||||||||||||||||||||||||||||||||||||
import api, { Flatfile } from "@flatfile/api" | ||||||||||||||||||||||||||||||||||||||||||
import type { FlatfileEvent, FlatfileListener } from '@flatfile/listener' | ||||||||||||||||||||||||||||||||||||||||||
import { updateRecords, Simplified } from "../../../utils/common/src" | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
export type Primitive = string | number | null | boolean | ||||||||||||||||||||||||||||||||||||||||||
export type SimpleRecord = Record<string, Primitive> | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
export function copyColumn() { | ||||||||||||||||||||||||||||||||||||||||||
return (listener: FlatfileListener) => { | ||||||||||||||||||||||||||||||||||||||||||
listener.on('workbook:created', async ({ context: { fileId, workbookId } }: FlatfileEvent) => { | ||||||||||||||||||||||||||||||||||||||||||
const { data: sheets } = await api.sheets.list({ workbookId }) | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
sheets.forEach(async (sheet) => { | ||||||||||||||||||||||||||||||||||||||||||
const loadAllFields = await getAllFields(sheets, sheet.slug); | ||||||||||||||||||||||||||||||||||||||||||
setSheetActions(sheet, [ | ||||||||||||||||||||||||||||||||||||||||||
copyColumnValuesBlueprint(loadAllFields), | ||||||||||||||||||||||||||||||||||||||||||
...(sheet.config.actions?.filter( | ||||||||||||||||||||||||||||||||||||||||||
(a) => | ||||||||||||||||||||||||||||||||||||||||||
a.operation !== 'copy-column' | ||||||||||||||||||||||||||||||||||||||||||
) || []), | ||||||||||||||||||||||||||||||||||||||||||
]); | ||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+13
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use 'for...of' loop instead of 'forEach' with async callbacks Using Apply this diff to fix the issue: - sheets.forEach(async (sheet) => {
+ for (const sheet of sheets) {
+ const loadAllFields = await getAllFields(sheets, sheet.slug);
+ await setSheetActions(sheet, [
+ copyColumnValuesBlueprint(loadAllFields),
+ ...(sheet.config.actions?.filter(
+ (a) =>
+ a.operation !== 'copy-column'
+ ) || []),
+ ]);
+ }
- const loadAllFields = await getAllFields(sheets, sheet.slug);
- setSheetActions(sheet, [
- copyColumnValuesBlueprint(loadAllFields),
- ...(sheet.config.actions?.filter(
- (a) =>
- a.operation !== 'copy-column'
- ) || []),
- ]);
- }) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
listener.on("job:ready", { job: "sheet:copy-column" }, async (e) => { | ||||||||||||||||||||||||||||||||||||||||||
const { records } = await e.data({ pageLength: 10_000 }) | ||||||||||||||||||||||||||||||||||||||||||
const { data: job } = await api.jobs.get(e.context.jobId) | ||||||||||||||||||||||||||||||||||||||||||
const { key_copy_from, key_paste_to } = job.input | ||||||||||||||||||||||||||||||||||||||||||
const patch = records.map(copyColumnValues(key_copy_from, key_paste_to)) | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+28
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validate input keys before copying column values There is no validation to ensure that Apply this diff to add validation: const { key_copy_from, key_paste_to } = job.input
+ if (!key_copy_from || !key_paste_to || key_copy_from === key_paste_to) {
+ throw new Error('Invalid input: Source and destination columns must be specified and cannot be the same.')
+ }
const patch = records.map(copyColumnValues(key_copy_from, key_paste_to)) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
await updateRecords(e.context.sheetId, patch) | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
await api.jobs.complete(e.context.jobId, { | ||||||||||||||||||||||||||||||||||||||||||
outcome: { | ||||||||||||||||||||||||||||||||||||||||||
message: `Data was successfully copied from ${key_copy_from} to ${key_paste_to}.`, | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
function copyColumnValues(from_key: string, to_key: string) { | ||||||||||||||||||||||||||||||||||||||||||
return (record: Flatfile.Record_) => { | ||||||||||||||||||||||||||||||||||||||||||
const obj = Simplified.toSimpleRecord(record) | ||||||||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||||||||
id: record.id, | ||||||||||||||||||||||||||||||||||||||||||
values: { | ||||||||||||||||||||||||||||||||||||||||||
[to_key]: { value: obj[from_key] }, | ||||||||||||||||||||||||||||||||||||||||||
flatfile-nullify[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||
* Set sheet actions | ||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||
* @param sheet | ||||||||||||||||||||||||||||||||||||||||||
* @param actions | ||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||
async function setSheetActions(sheet: any, actions: Flatfile.Action[]) { | ||||||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||||||
const { constraints } = sheet.config; | ||||||||||||||||||||||||||||||||||||||||||
await api.workbooks.update(sheet.workbookId, { | ||||||||||||||||||||||||||||||||||||||||||
sheets: [ | ||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||
name: sheet.name, | ||||||||||||||||||||||||||||||||||||||||||
slug: sheet.config.slug, | ||||||||||||||||||||||||||||||||||||||||||
actions, | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
if (constraints?.length > 0) { | ||||||||||||||||||||||||||||||||||||||||||
await api.workbooks.update(sheet.workbookId, { | ||||||||||||||||||||||||||||||||||||||||||
sheets: [ | ||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||
...sheet, | ||||||||||||||||||||||||||||||||||||||||||
config: { | ||||||||||||||||||||||||||||||||||||||||||
...sheet.config, | ||||||||||||||||||||||||||||||||||||||||||
actions, | ||||||||||||||||||||||||||||||||||||||||||
constraints, | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
} catch (e) { | ||||||||||||||||||||||||||||||||||||||||||
console.log({ e }); | ||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+88
to
+89
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance error handling in the 'setSheetActions' function Currently, the error is logged using Apply this diff to improve error handling: } catch (e) {
- console.log({ e });
+ console.error('Error updating sheet actions:', e);
+ throw e;
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
export const getAllFields = (sheets, sheetSlug) => { | ||||||||||||||||||||||||||||||||||||||||||
const _fields = sheets.reduce((acc, sheet) => { | ||||||||||||||||||||||||||||||||||||||||||
console.log("in getallfields, sheet.config.fields here: ") | ||||||||||||||||||||||||||||||||||||||||||
console.log(sheet.config) | ||||||||||||||||||||||||||||||||||||||||||
if (sheet.config.slug == sheetSlug) { | ||||||||||||||||||||||||||||||||||||||||||
acc.push( | ||||||||||||||||||||||||||||||||||||||||||
...sheet.config.fields | ||||||||||||||||||||||||||||||||||||||||||
.map((f) => { | ||||||||||||||||||||||||||||||||||||||||||
return { ...f, appearance: { size: "s" } } as const | ||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
return acc | ||||||||||||||||||||||||||||||||||||||||||
}, [] as Flatfile.Property[]) | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
return _fields | ||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
export const copyColumnValuesBlueprint = (columns: Flatfile.Property[]): Flatfile.Action => ({ | ||||||||||||||||||||||||||||||||||||||||||
label: "Copy Column", | ||||||||||||||||||||||||||||||||||||||||||
primary: false, | ||||||||||||||||||||||||||||||||||||||||||
operation: "copy-column", | ||||||||||||||||||||||||||||||||||||||||||
inputForm: { | ||||||||||||||||||||||||||||||||||||||||||
type: "simple", | ||||||||||||||||||||||||||||||||||||||||||
fields: [ | ||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||
key: "key_copy_from", | ||||||||||||||||||||||||||||||||||||||||||
type: "enum", | ||||||||||||||||||||||||||||||||||||||||||
label: "Copy data from column", | ||||||||||||||||||||||||||||||||||||||||||
config: { | ||||||||||||||||||||||||||||||||||||||||||
options: columns | ||||||||||||||||||||||||||||||||||||||||||
.map((f) => ({ label: f.label, value: f.key })) | ||||||||||||||||||||||||||||||||||||||||||
.sort((a, b) => a.label.localeCompare(b.label)), | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
constraints: [{ type: "required" }], | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||
key: "key_paste_to", | ||||||||||||||||||||||||||||||||||||||||||
type: "enum", | ||||||||||||||||||||||||||||||||||||||||||
label: "Paste data to column", | ||||||||||||||||||||||||||||||||||||||||||
config: { | ||||||||||||||||||||||||||||||||||||||||||
options: columns | ||||||||||||||||||||||||||||||||||||||||||
.map((f) => ({ label: f.label, value: f.key })) | ||||||||||||||||||||||||||||||||||||||||||
.sort((a, b) => a.label.localeCompare(b.label)), | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
constraints: [{ type: "required" }], | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './copy-column' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat to populate all the field enums for each sheet!
Does this
workbook:created
event get triggered for File based Workbooks? Would we want to add the Action on everyworkbook:created
orsheet:created
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not seeing
sheet:created
when creating a space. What do you mean by File based Workbooks?