Copying links when copying rows with js

Your Setup:

  • SeaTable Enterprise Edition 5.2.7, on prem

Describe the Problem/Error/Question:

I want to copy a row using javascript from a button. Except for the links this is already working.

// Define the async function to copy the current row, including links
async function copyCurrentRowWithLinks() {
  try {
    // Get current table and view context
    const table = base.context.currentTable;
    const tableId = base.getTableByName(table)["_id"];
    const rowId = base.context.currentRow["_id"];

    // Fetch columns to ensure table reference is correct
    const columns = await base.getColumns(table);

    // Get the specified row using its ID
    const row = await base.getRow(table, rowId);

    // Define fields to exclude from the copying process
    const excludeFields = ["_id"]; // Add additional fields as needed

    // Filter the fields in the row
    const filteredRowData = Object.fromEntries(
      Object.entries(row).filter(([key]) => !excludeFields.includes(key))
    );

    // Copy the row by appending a new row with the filtered data
    const newRow = await base.appendRow(table, filteredRowData);
    const newRowId = newRow._id;

    // Process of copying links
    for (const column of columns) {
      // Specifically check for link columns
      if (column.type === 'link') {
        const linkColumnKey = column.key; // Correctly using the column key

        try {
          // Fetch the linked records for this specific link column
          const linkedRecords = await base.getLinkedRecords(tableId, linkColumnKey, [{ 'row_id': rowId }]);

          if (linkedRecords[rowId]) {
            for (const linkedRow of linkedRecords[rowId]) {
              // Use column's link ID and "other_table_id" to link correctly
              await base.addLink(column.data.link_id, table, column.data.other_table_id, newRowId, linkedRow.row_id);
            }
          }
        } catch (getLinkedRecordsError) {
          console.error(`Error while fetching linked records for column ${column.name}:`, getLinkedRecordsError);
        }
      }
    }
  } catch (error) {
    console.error('Error copying row or links:', error);
    console.error('Detailed error:', error.response ? error.response.data : 'No additional error data');
  }
}

// Call the function to copy the current row with links
copyCurrentRowWithLinks();

There is no error whatsover, it is just not copying the links. I think the culprit is the base.addLink method. It expects table names for both tables that are linked. During the base.getLinkedRecords method the name is not returned though and therefore can’t be added to the adding method.

Did I miss something or is this just not working by design?

Hi @vqui,
I think you actually missed the fact that the base.addLink function expects the name of both tables, whereas column.data.other_table_id contains the id of the table… Here it what I did to make it work:

  1. Somewhere at the beginning, get a const of every tables const tables = base.getTables();
  2. In your if (column.type === 'link') statement, get the linked table by filtering your ta by tryig to match the column.data.other_table_id. If one single table is returned, you can get its name for the base.addLink function

Here is the final code:

// Define the async function to copy the current row, including links
async function copyCurrentRowWithLinks() {
  try {
    // Get current table and view context
    const table = base.context.currentTable;
    const tableId = base.getTableByName(table)["_id"];
    const rowId = base.context.currentRow["_id"];
    const tables = base.getTables();

    // Fetch columns to ensure table reference is correct
    const columns = await base.getColumns(table);

    // Get the specified row using its ID
    const row = await base.getRow(table, rowId);

    // Define fields to exclude from the copying process
    const excludeFields = ["_id"]; // Add additional fields as needed

    // Filter the fields in the row
    const filteredRowData = Object.fromEntries(
      Object.entries(row).filter(([key]) => !excludeFields.includes(key))
    );

    // Copy the row by appending a new row with the filtered data
    const newRow = await base.appendRow(table, filteredRowData);
    const newRowId = newRow._id;

    // Process of copying links
    for (const column of columns) {
      // Specifically check for link columns
      if (column.type === 'link') {
        const linkColumnKey = column.key; // Correctly using the column key
        const linkedTable = tables.filter((tab) => tab._id == column.data.other_table_id);
        if (linkedTable.length==1) { // Verifying that the filters returns one single table
          try {
            // Fetch the linked records for this specific link column
            const linkedRecords = await base.getLinkedRecords(tableId, linkColumnKey, [{ 'row_id': rowId }]);
            if (linkedRecords[rowId]) {
              for (const linkedRow of linkedRecords[rowId]) {
                // Use column's link ID and "other_table_id" to link correctly
                await base.addLink(column.data.link_id, table, linkedTable[0].name, newRowId, linkedRow.row_id);
              }
            }
          } catch (getLinkedRecordsError) {
            console.error(`Error while fetching linked records for column ${column.name}:`, getLinkedRecordsError);
          }
        }
      }
    }
  } catch (error) {
    console.error('Error copying row or links:', error);
    console.error('Detailed error:', error.response ? error.response.data : 'No additional error data');
  }
}

// Call the function to copy the current row with links
copyCurrentRowWithLinks();
output.text('script terminé')

One last remark : to get the specified row, (l.14 in my version) you can directly use base.context.currentRow: whereas base.context.currentTable just rename the name of the current table, base.context.currentRow actually returns the whole row object.

Bests,
Benjamin


I love spending time gathering information and explaining solutions to help you solve your problems. I spend… quite a bit of time on it :sweat_smile: .If you feel grateful for the help I’ve given you, please don’t hesitate to support me. I am also available for paid services (scripts, database architecture, custom development, etc.).

2 Likes

Thank you very much. Your changes worked immediately!

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.