Help

Record timer script

14074 32
cancel
Showing results for 
Search instead for 
Did you mean: 

Inspired by this discussion, I wrote a script for the Scripting block that lets you instantly start and stop a virtual timer on any record, provided that the table is set up to work with this script. Aside from adding the script into a Scripting block, setup only requires three new fields:

  1. A single line text field, which will store the script’s timing data (used internally; may be hidden)
  2. A duration field, where the script will store the tracked time
  3. A button field, which must be set to trigger the Scripting block that contains the script. I suggest labeling this button “Start/Stop,” for reasons that you’ll see below.

Use: Click the button once to start the “timer.” Click it again to stop it and see the duration. Need to continue timing on that same record? Click the button again to restart. The next click after that will tally the elapsed time from both timing “sessions” and put the total in the duration field. Start and stop the timer as much as you need.

How it works: Each time you click the button, the script adds the current time (converted to a number) to an array, and stores that array in the single line text field. An time that a button click results in an even number of values in the array, the script calculates the difference between each pair of values, and stores the resulting duration in the duration field.

The benefit of this timer system is that you can have multiple records all “timing” simultaneously, and all using the same Scripting block. Using Airtable’s timer block, you first have to pick a record for the timer, and you need one timer block per record that you wish to time.

One optional feature in the script is to clear the duration field while the timer is “active.” This is one possible way to avoid confusion when looking at a record and wondering whether the timer is active or not. :slightly_smiling_face: It’s not exactly a status indicator, but it’s a first start. I’ve got some other ideas that I plan on adding to later updates, including optional status indicators (text/emojis), and an alternate method of starting/stopping the timer using automation so that the blocks sidebar doesn’t need to be involved.

Here’s the script.

32 Replies 32

Welcome to the community, @Operations_ACM! :grinning_face_with_big_eyes: Unfortunately finding energy for personal projects has been extremely difficult ever since I went from full-time consultant to full-time employee earlier this year. Now I’m working in Airtable and writing code all day, and as much as I enjoy it, it’s tough to do more of the same after hours. It’s still on my list of things to tackle, but I honestly have no idea when I’ll get to it. Sorry.

Hey Justin! Thanks for the warm welcome :star_struck:
No worries, I totally get it & hopefully you manage some inspiration to in the near future. Good luck with your new role and take care :slightly_smiling_face:

Thanks Justin for the original script. I had Claude help me modify it to create a time log in another table. Hope this is useful to anyone.

/**
 * Title: Enhanced Record Timer with Detailed Logging
 * Version: 2.3
 * License: MIT
 * Original Author: Justin Barrett
 * Modified by: Claude (Anthropic)
 * 
 * Description: An enhanced version of the Record Timer script. This script creates
 * detailed time logs in a separate table, tracking assignments, status, and linking
 * to the original record. It avoids creating entries with zero duration and always
 * creates a new log entry for each timing session.
 */

// ------------------------ START CONFIGURATION ------------------------//

let dataField = "Timer Data";
let durationField = "Duration";
let assignedToField = "Assigned to:";
let statusField = "Status";
let orderField = "Order"; // Add this line, assuming you have an "Order" field

let timeLogsTableName = "Time Logs";
let timeLogsFields = {
    recordId: "Record ID",
    assignedPerson: "Assigned Person",
    duration: "Duration",
    timestamp: "Timestamp",
    recordLink: "Record Link",
    status: "Status"
};

// ------------------------- END CONFIGURATION -------------------------//

// Get the tables
let ordersTable = base.getTable(cursor.activeTableId);
let timeLogsTable = base.getTable(timeLogsTableName);

// Get the record
let record = await input.recordAsync("Choose a record", ordersTable);
let recordId = record.id;
let timerData = record.getCellValue(dataField);
let assignedTo = record.getCellValueAsString(assignedToField);
let status = record.getCellValueAsString(statusField);
let orderInfo = record.getCellValueAsString(orderField) || "No order specified"; // Add this line
let values = timerData === null ? [] : JSON.parse(timerData);

// Get the current time
let currentTime = new Date();
let currentTimestamp = currentTime.getTime();
values.push(currentTimestamp);

// Calculate total duration
let totalDuration = 0;
for (let i = 0; i < values.length; i += 2) {
    if (+ 1 < values.length) {
        totalDuration += values[+ 1] - values[i];
    } else {
        totalDuration += currentTimestamp - values[i];
    }
}
totalDuration = Math.round(totalDuration / 1000); // Convert to seconds

// Calculate duration of the current session
let currentSessionDuration = 0;
if (values.length % 2 === 0) {
    currentSessionDuration = Math.round((currentTimestamp - values[values.length - 2]) / 1000); // in seconds
}

// Only proceed with time log creation if there is a duration
if (currentSessionDuration > 0) {
    // Prepare data for the time log
    let timeLogData = {
        [timeLogsFields.recordId]: recordId,
        [timeLogsFields.assignedPerson]: assignedTo,
        [timeLogsFields.duration]: currentSessionDuration,
        [timeLogsFields.timestamp]: currentTime,
        [timeLogsFields.recordLink]: [{id: recordId}],
        [timeLogsFields.status]: status
    };

    // Always create a new log entry
    await timeLogsTable.createRecordAsync(timeLogData);
}

// Update the original record
await ordersTable.updateRecordAsync(record, {
    [dataField]: JSON.stringify(values),
    [durationField]: totalDuration
});

output.markdown(`# Timer ${values.length % 2 === 0 ? 'Stopped' : 'Started'}

**Order:** ${orderInfo}
**Record ID:** ${recordId}
**Assigned To:** ${assignedTo}
**Status:** ${status}
**Total Duration:** ${totalDuration} seconds
**Current Session Duration:** ${currentSessionDuration} seconds
**Timestamp:** ${currentTime.toISOString()}
${currentSessionDuration === 0 ? '\n**Note:** No time log entry was created due to zero duration.' : ''}
`);