diff --git a/.changeset/dull-apes-deny.md b/.changeset/dull-apes-deny.md new file mode 100644 index 000000000..83ed7aeb8 --- /dev/null +++ b/.changeset/dull-apes-deny.md @@ -0,0 +1,5 @@ +--- +'@flatfile/plugin-view-mapped': patch +--- + +This release fixes a bug in the view-mapped plugin when multiple sheets have fields with the same key by limiting the view-mapped update to the sheet being mapped. Additionally, the view-mapped plugin now only runs when the `trackChanges` setting in the workbook is enabled to prevent a race condition where the view-mapped plugin runs before hooks have completed. diff --git a/plugins/view-mapped/src/view-mapped.ts b/plugins/view-mapped/src/view-mapped.ts index c4a4d05ad..66fca9a1e 100644 --- a/plugins/view-mapped/src/view-mapped.ts +++ b/plugins/view-mapped/src/view-mapped.ts @@ -1,10 +1,12 @@ -import { FlatfileClient } from '@flatfile/api' +import { type Flatfile, FlatfileClient } from '@flatfile/api' import type { FlatfileListener } from '@flatfile/listener' import { jobHandler } from '@flatfile/plugin-job-handler' import { logError } from '@flatfile/util-common' const api = new FlatfileClient() +const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) + /** * This plugin allows you to make the post-mapping sheet only display mapped data */ @@ -48,6 +50,10 @@ export function viewMappedPlugin() { // Obtaining the mapping job's execution plan to later extract "fieldMapping" out of it, which tells us which fields were mapped in the Matching step const jobPlan = await api.jobs.getExecutionPlan(mappingJobId) + const destinationSheetId = ( + jobPlan.data.job.config as Flatfile.MappingProgramJobConfig + ).destinationSheetId + // Initializing an empty array to store the keys of the mapped fields const mappedFields = [] @@ -65,13 +71,23 @@ export function viewMappedPlugin() { // We need to make this API call and cannot just use what's inside of "workbookOne" because we need data in a specific format const { data: workbook } = await api.workbooks.get(workbookId) + // If trackChanges is not enabled, we skip the rest of the job. This configuration is required to provide the plugins with the + // awareness that all hooks have run. Without it, we run into a race condition between the hook and the Workbook update. If the + // Workbook update runs before the hook, the hook will not be able to update the Workbook. + if (!workbook.settings.trackChanges) { + console.log('Skipping because trackChanges is not enabled') + return + } + // Looping through all sheets of the Workbook One. For all fields that are mapped, updating those fields' metadata to "{mapped: true}" workbook.sheets.forEach((sheet) => { - sheet.config.fields.forEach((field) => { - if (mappedFields.includes(field.key)) { - field.metadata = { mapped: true } - } - }) + if (sheet.id === destinationSheetId) { + sheet.config.fields.forEach((field) => { + if (mappedFields.includes(field.key)) { + field.metadata = { mapped: true } + } + }) + } }) // Looping over each sheet in "workbook" and filtering for fields with metadata "mapped: true". Saving mapped fields per each sheet inside of "filteredWorkbookFields" varibable @@ -104,6 +120,23 @@ export function viewMappedPlugin() { await tick(80, 'plugins.viewMapped.almostDone') + // Check that all commits are completed before running this job + let hasUncompletedCommits = true + do { + const { data: commits } = await api.sheets.getSheetCommits( + destinationSheetId, + { + completed: false, + } + ) + console.log(`Waiting on ${commits.length} commits to complete...`) + hasUncompletedCommits = commits.length > 0 + if (hasUncompletedCommits) { + // We wait for 200ms between each check to avoid making too many requests to the API + await sleep(200) + } + } while (hasUncompletedCommits) + // Updating each sheet in a workbook to only contain fields that a user mapped. This ensures that when the table with data loads, only mapped fields will be displayed await api.workbooks.update(workbookId, { // Keeping other non-sheet elements of the workbook untouched (Workbook name, its Submit action, etc)