Developer Portal for YouTrack and Hub Help

Stopwatch-style Work Timer

This workflow enables a timer that tracks the amount of time spent working on an issue. The behavior is similar to the In Progress Work Timer. Instead of using the value for the State to start and stop the timer, this workflow uses the values for an independent Timer field.

Use this workflow when you want to track time spent working on an issue without affecting the value for the State field.

Name

@jetbrains/youtrack-workflow-standalone-work-timer

Previous Title

Standalone Work Timer

Auto-attached

no

Modules

Start timer when the value for "Timer" becomes "Start" (on-change rule)

Stop timer when the value for "Timer" becomes "Stop" (on-change rule)

To enable this workflow:

  1. Enable and configure time tracking for your project. For instructions, see Enable Time Tracking instruction.

  2. Add a field that stores an enum type with the name Timer to your project.

    • Configure the field to store a single value.

    • Configure the field to allow an empty value.

    • Add the values Start and Stop to the field.

  3. Add a field that stores a date and time type with the name Timer time to your project.

  4. Attach the Stopwatch-style Work Timer workflow to your project.

Use Case

This workflow enables a timer that you can use to track the amount of time you spend working on an issue. When you stop the timer, the elapsed time is automatically added to the issue as a work item.

  1. When you start working on an issue, set the value of the Timer field to Start.

    • The workflow displays the message: The timer is started.

    • The value for the Timer time field is set to the current date and time.

  2. Continue working as you would with any other issue. Try to avoid distractions — the clock is ticking!

  3. When you have completed your work, change the value of the Timer field to Stop.

    • The workflow displays the message: Work time added.

    • A work item is added to the issue.

Each work item is assigned the following values:

  • The current user is set as the work author.

  • The work date is set to the current date with the Date.now() method.

  • The comment is set to: The work item automatically added by the timer.

  • The spent time is calculated based on the difference between the value for the Timer time field and the current date and time.

The workflow does not assign a work type to work items. If you want to add a specific work type programmatically, you can modify the on-change rule that stops the timer and generates the work item. For an example, see the suggested customization for the Stop timer when the value for "Timer" becomes "Stop" rule.

Modules

This workflow includes two modules.

Start timer when the value for "Timer" becomes "Start"

The first module contains an on-change rule that starts the timer.

const entities = require('@jetbrains/youtrack-scripting-api/entities'); const workflow = require('@jetbrains/youtrack-scripting-api/workflow'); exports.rule = entities.Issue.onChange({ title: 'Start timer when the value for "Timer" becomes "Start"', guard: (ctx) => { return ctx.issue.fields.becomes(ctx.Timer, ctx.Timer.Start); }, action: (ctx) => { ctx.issue.fields.TimerTime = Date.now(); workflow.message('The timer is started.'); }, requirements: { Timer: { type: entities.EnumField.fieldType, Start: {} }, TimerTime: { type: entities.Field.dateTimeType, name: 'Timer time' } } });

The second module contains an on-change rule that stops the timer. The elapsed time is added to the issue as a work item.

Stop timer when the value for "Timer" becomes "Stop"

const entities = require('@jetbrains/youtrack-scripting-api/entities'); const workflow = require('@jetbrains/youtrack-scripting-api/workflow'); exports.rule = entities.Issue.onChange({ title: 'Stop timer when the value for "Timer" becomes "Stop"', guard: (ctx) => { return ctx.issue.fields.becomes(ctx.Timer, ctx.Timer.Stop) && ctx.issue.fields.TimerTime; }, action: (ctx) => { const issue = ctx.issue; if (issue.fields.was(ctx.Timer, ctx.Timer.Start)) { let duration = issue.project.intervalToWorkingMinutes(issue.fields.TimerTime, Date.now()); if (duration) { const newWorkItem = { description: workflow.i18n('The work item automatically added by the timer.'), date: Date.now(), author: ctx.currentUser, duration: duration }; issue.addWorkItem(newWorkItem); workflow.message('Work time added'); } } else { workflow.message('Looks like the timer hasn\'t been started.'); } }, requirements: { Timer: { type: entities.EnumField.fieldType, Stop: {}, Start: {} }, TimerTime: { type: entities.Field.dateTimeType, name: 'Timer time' } } });

The default workflow doesn't set a value for the work type. If you want to set a default work type for work items that are generated by this workflow, you can customize this rule.

The following code shows an alternative approach for setting the action property. Here, the workItemType variable finds the work item type in the current project with the name Development and adds it to the work item.

action: (ctx) => { const issue = ctx.issue; if (issue.fields.oldValue(ctx.Timer).name === ctx.Timer.Start.name) { const workItemType = entities.WorkItemType.findByProject(ctx.issue.project).find(function (workType) { return workType.name === 'Development'; }); const newWorkItem = { description: workflow.i18n('The work item automatically added by the timer.'), date: Date.now(), author: ctx.currentUser, type: workItemType, duration: issue.project.intervalToWorkingMinutes(issue.fields.TimerTime, Date.now()) }; issue.addWorkItem(newWorkItem); workflow.message(workflow.i18n('Work time added')); } else { workflow.message(workflow.i18n('Looks like the timer hasn\'t been started.')); } }
Last modified: 7 October 2024