# Forgotten Attachment

This workflow reminds users to add an attachment to an issue if an attachment is mentioned in a description or comment.

| Name | @jetbrains/youtrack-workflow-forgotten-attachment |
| Auto-attached | no |
| Modules |    [Check description for reference to attachment](#check-description-for-attachment-reference) (on-change rule)     [Check comment for reference to attachment](#check-comment-for-attachment-reference) (on-change rule)      [attach-file-utils.js](#attach-file-utility) (custom script)     |

## Use Case

This workflow helps to make sure that users remember to attach a file to an issue when they reference an attachment in a description or comment.

## Modules

This workflow contains two modules that can be attached as rules to a project and a third module that contains a custom script. This script contains common functions that are used in both rules.

### Check description for reference to attachment

The first module contains a rule that scans the description for references to an attachment. If a reference is found, the user is reminded to attach a file to the issue.

```JAVASCRIPT
const entities = require('@jetbrains/youtrack-scripting-api/entities');
const utils = require('./attach-file-utils');

exports.rule = entities.Issue.onChange({
  title: 'Check description for reference to attachment',
  guard: (ctx) => {
    return ctx.issue.becomesReported || ctx.issue.isChanged('description'); // optimize blob (description) read
  },
  action: (ctx) => {
    const issue = ctx.issue;

    const description = issue.description;
    if (!description) {
      return;
    }

    if (issue.becomesReported && ctx.issue.attachments.isEmpty()) {
      utils.findAndShowMessage(description);
      return;
    }
    if (issue.isChanged('description')) {
      const oldDescription = issue.oldValue('description') || '';
      let found = '';
      if (utils.words().some(function (word) {
        if ((description.indexOf(word) > -1) && (oldDescription.indexOf(word) === -1)) {
          found = word;
          return true;
        }
        return false;
      })) {
        utils.showMessage(found);
      }
    }
  }
});
```

### Check comment for reference to attachment

The second module contains a rule that scans new comments for references to an attachment. If a reference is found, the user is reminded to attach a file to the issue.

```JAVASCRIPT
const entities = require('@jetbrains/youtrack-scripting-api/entities');
const utils = require('./attach-file-utils');

exports.rule = entities.Issue.onChange({
    title: 'Check comment for reference to attachment',
    guard: (ctx) => {
        return !ctx.issue.comments.added.isEmpty();
    },
    action: (ctx) => {
        ctx.issue.comments.added.forEach(function (comment) {
            if (comment.attachments.isEmpty()) {
                utils.findAndShowMessage(comment.text);
            }
        });
    }
});
```

### attach-file-utils.js

The last module contains the code that both rules use to determine whether a description or comment contains a reference to attachment. This script also contains the code that displays the message to the user.

```JAVASCRIPT
const workflow = require('@jetbrains/youtrack-scripting-api/workflow');

exports.words = function () {
  return 'attachments, attachment, attached, attaches, attach, attaching'.split(', ');
};

exports.showMessage = function (what) {
  workflow.message('You have mentioned the "{0}" word, don\'t forget to attach it (them).', what);
};

exports.findAndShowMessage = function (text) {
  let found = '';
  if (exports.words().some(function (word) {
    if (text.indexOf(word) > -1) {
      found = word;
      return true;
    }
    return false;
  })) {
    exports.showMessage(found);
  }
};
```

> **Warning: Localized Messages**
> The original workflow script provided by YouTrack uses the `workflow.i18n` function. This is an internal function that is only meant to be used to reference localized message strings. To ensure that you can copy and customize this workflow code, we have removed this function from the sample. If you are editing the default workflow and want to customize any message text, we recommend that you remove these functions from your code as well.
>
>
>
> To learn more about localized messages in workflows, see [Localized Workflow Messages](Workflow-Localization.html).

