Showcase: Script to save drag-drop sort order in views

UPDATE: You can replace the first part of this example case with the formula mentioned here: Showcase: Script to save drag-drop sort order in views - #2 by Chr1sG


Problem It Solves

In Fibery, manually drag-dropping entities in views updates their hidden Rank values, but these values are inaccessible to users. This script provides a workaround by:

  1. Fetching the hidden Rank values.
  2. Converting them into sequential Weight numbers that users can see and use.

Example use case

You want users to drag-drop a list of entities, but you don’t want them to manually have to update the weight or sorting value. For example in this case a list of AI Steps in a Pipeline.
With this script below, after manually drag-dropping, one button click saves the sort order.

Extended functionality

In addition to assigning Weight values for sort order tracking, in the example video you see two automations follow up with:

  • Use the Weight values to update a Prefix field.
  • Combine the Prefix with a Title to dynamically update the entity’s Name.

What This Script Does

This script organizes StepRun entries in a PipeRun by assigning a simple, sequential Weight based on their Rank. The Rank field in Fibery is a hidden, very large number that users cannot access or edit directly, so this script translates it into a manageable and clear order.


How It Works

  1. Fetch StepRuns:

    • Retrieves all StepRun entries linked to a PipeRun, including their hidden Rank values.
  2. Sort by Rank:

    • Sorts the StepRuns from smallest to largest Rank to determine their order.
  3. Assign Weights:

    • Assigns sequential Weight values (1, 2, 3, etc.) based on the sorted order.
  4. Update Fibery:

    • Saves the updated Weight values back to Fibery for each StepRun.

Example

Before the Script:

  • StepRuns have inaccessible Rank values like 1234567890123456, 1234567890123452, and 1234567890123458. Weight is blank or incorrect.

After the Script:

  • Sorted by Rank:
    • Rank 1234567890123452 → Weight 1
    • Rank 1234567890123456 → Weight 2
    • Rank 1234567890123458 → Weight 3

Additional Functionality:

This script also ensures that StepRun Names reflect their updated Weight:

  1. Weight to Prefix:

    • When a StepRun’s Weight is updated, it triggers an automation to convert the Weight into the Prefix (e.g., 1. for Weight 1).
  2. Prefix to Name:

    • When the Prefix is updated, it triggers another automation to update the Name by combining the Prefix with the Title (e.g., 1. Task Title).

Demonstration Video

Script (the basic functionality of setting Weight values)

const fibery = context.getService('fibery');

// -----------------------------------
// DATABASE CONFIGURATION
// -----------------------------------
const PIPERUN_DB = {
    NAME: 'AI/PipeRun',     // Database name for PipeRun
    STEP_RUNS_FIELD: 'StepRuns' // Field in PipeRun linking to child StepRun entities
};

const STEPRUN_DB = {
    NAME: 'AI/StepRun',       // Database name for StepRun
    RANK_FIELD: 'Rank',       // Numeric Rank field
    WEIGHT_FIELD: 'Weight'    // Numeric field to store sequential numbering
};

// -----------------------------------
// MAIN FUNCTION
// -----------------------------------
async function updateStepRunWeights() {
    try {
        // Get the current PipeRun entity
        const currentEntity = args.currentEntities[0];
        if (!currentEntity) {
            console.error('No current PipeRun entity provided.');
            return;
        }

        // Fetch the PipeRun entity along with its StepRuns
        const pipeRun = await fibery.getEntityById(
            PIPERUN_DB.NAME,
            currentEntity.id,
            [PIPERUN_DB.STEP_RUNS_FIELD] // Retrieve StepRuns relation field
        );

        const stepRuns = pipeRun[PIPERUN_DB.STEP_RUNS_FIELD];
        if (!stepRuns || stepRuns.length === 0) {
            console.log(`No StepRuns found for PipeRun ID ${currentEntity.id}.`);
            return;
        }

        console.log(`Found ${stepRuns.length} StepRuns. Processing...`);

        // Array to store StepRuns for sorting
        const stepRunsData = [];

        // Retrieve Rank for sorting
        for (const stepRunRef of stepRuns) {
            const stepRun = await fibery.getEntityById(
                STEPRUN_DB.NAME,
                stepRunRef.Id,
                [STEPRUN_DB.RANK_FIELD]
            );

            stepRunsData.push({
                id: stepRun.Id,
                rank: stepRun[STEPRUN_DB.RANK_FIELD]
            });
        }

        // Sort StepRuns by Rank (ascending)
        stepRunsData.sort((a, b) => a.rank - b.rank);

        // Assign sequential Weight values
        for (let i = 0; i < stepRunsData.length; i++) {
            const stepRun = stepRunsData[i];
            const weightValue = i + 1; // Start with 1 and increment

            // Update the Weight field
            await fibery.updateEntity(STEPRUN_DB.NAME, stepRun.id, {
                [STEPRUN_DB.WEIGHT_FIELD]: weightValue
            });

            console.log(`Assigned Weight ${weightValue} to StepRun ID ${stepRun.id}`);
        }

        console.log(`All StepRuns for PipeRun ID ${currentEntity.id} have been updated.`);
    } catch (error) {
        console.error('Error in script:', error);
    }
}

// Execute the function
await updateStepRunWeights();

2 Likes

For reference, in some cases, a formula can be used to get the rank order of items (within a collection):

1 Like

That is an amazing solution @Chr1sG thank you! I will link it to the top of the topic.

A minor limitation I have found is that it returns always a float and not an integer, so the values are 1.0 2.0 etc.

The part of the formula responsible is likely this:

(Find(...) + 4) / 5

When you divide by 5, even if the result is mathematically a whole number (e.g., 10 / 5 = 2), the system interprets it as a floating-point number (e.g., 2.0).

I could not find a way to make it an integer, but its not a big deal, since the value will mostly be used for another automation (like populating a Weight field) so it will be hidden anyway.

Just choose zero decimal places when you create the formula

I tried but it does not allow me:

You have to do it at the time of creating the formula

1 Like

That worked, thank you!