RESOLVED: Cannot change state in workflow

Hello,

I need to change State state, but it doesn't work. I don't get any errors, just nothing happens.

/* eslint-disable */
var entities = require('@jetbrains/youtrack-scripting-api/entities');
var workflow = require('@jetbrains/youtrack-scripting-api/workflow');




exports.rule = entities.Issue.onChange({
  title: "Rule 1 test",
  // --- --- ---
  // Guard
  guard: function(ctx) {
    // --- #1 checkField ---
    const issue_0 = ctx.issue;

    function checkFieldStateState_0() {
      // Return true if the 'State' field was changed from 'Waiting For Info' to any
      return issue_0.fields.isChanged(ctx.StateState) && issue_0.fields.was(ctx.StateState, ctx.StateState.WaitingForInfo);
    }
    
    const checkFieldFn_0 = () => {
      return checkFieldStateState_0();
    };
    
    try {
      return (
        checkFieldFn_0()
      );
    } catch (err) {
      if (err.message.includes('has no value')) {
        console.error('Failed to execute guard');
        return false;
      }
      throw err;
    }
    
  },
  // Guard end
  // --- --- ---
  // Action
  action: function(ctx) {
    console.log("Running scripts in Action section");
    // --- #1 'Waiting For Info' --> 'Info Done'
    const issue_1 = ctx.issue;

    // Return true if the 'State' field was changed from 'Waiting For Info' to 'Info Done'
    function checkFieldStateState_1() {
      return issue_1.fields.isChanged(ctx.StateState) && issue_1.fields.was(ctx.StateState, ctx.StateState.WaitingForInfo) && issue_1.fields.becomes(ctx.StateState, ctx.StateState.InfoDone);
    }

    const checkFieldFn_1 = () => {
      return checkFieldStateState_1();
    };
    // If the 'State' field was changed from 'Waiting For Info' to 'Info Done'
    if (checkFieldFn_1()) {
      // --- #2 User is among allowed users (WFI users, Assignee or Reporter) ---
      console.log("Block #2: Running scripts for the \"User Is Among WFI Users\" block");
      const curr_user = ctx.currentUser.login;
      const assn_user = issue_1.fields.Assignee.login;
      const rprt_user = issue_1.reporter.login;
      
      //console.log(curr_user); // Current user
      //console.log(assn_user); // Assignee user
      //console.log(rprt_user); // Reporter (author) user
      
      if (curr_user === null || curr_user === undefined) throw new Error('Block #2 "Current user" has no value');
      if (assn_user === null || assn_user === undefined) throw new Error('Block #2 "Assigned user" has no value');
      if (rprt_user === null || rprt_user === undefined) throw new Error('Block #2 "Reporter user" has no value');
      
      // User is among WFI Users
      const UserIsAmongWFIUsers = () => {
        var UserIsIn = false;
        issue_1.fields["Waiting For"].forEach(function(username){
          if (curr_user === username.login){
            UserIsIn = true;
          }
        });
        return UserIsIn;
      };

      const UserhasRoleFn_0 = () => {
        return UserIsAmongWFIUsers() || curr_user === rprt_user || curr_user === assn_user;
      };

      let ifOperatorResult_0;
      if (UserhasRoleFn_0()) {
        // --- #3 changeIssueFieldValue ---
        console.log("Block #2: Removing user from WFI list");
        //console.log("Current value:", issue_1.fields["Waiting For"]);
        
        // Remove current user from the WFI list
        const changeIssueFieldValueFn_0 = () => {
          issue_1.fields["Waiting For"].delete(ctx.currentUser);
          //console.log(issue_1.fields["Waiting For"]);
        };
        if(UserIsAmongWFIUsers()){
          changeIssueFieldValueFn_0();
          if(issue_1.fields["Waiting For"].isEmpty()){
          // Changing State from InfoDone to Open if no WFI Users left
// it looks like this part of the code doesn't work, the State doesn't change
            issue_1.StateState = ctx.StateState.Open;
            console.log("Block #2: State is changed to Open");
          } else {
// Changing State from InfoDone to WaitingForInfo if there is WFI Users left
            issue_1.StateState = ctx.StateState.WaitingForInfo;
            console.log("Block #2: State is changed to WFI");
          }
        }
        
        ifOperatorResult_0 = true;
      } else {

        // --- #4 notify user ---
        console.log("User does not have the rights");
        const message_0 = `Error: You do not have the rights to change the State`;
        console.log(message_0);
        
        const notifyUserFn_0 = () => {
          return workflow.message(message_0);
        };
        
        ifOperatorResult_0 = notifyUserFn_0();
      }
      
      const ifOperatorFn_0 = () => {
        return ifOperatorResult_0;
      };
      
      const conditionalRevertFn_0 = () => {
        workflow.check(ifOperatorFn_0(),"Can't touch this! stop!");
      };

      conditionalRevertFn_0();

    } else {
      console.log("User is not among allowed users");
    }

    const ifOperatorFn_3 = () => {
    };
    
    ifOperatorFn_3();

  },
  // Action end
  // --- --- ---
  // Requirements
  requirements: {
    StateState: {
      name: "State",
      type: entities.State.fieldType,
      WaitingForInfo: {name: "Waiting For Info"},
      InfoDone: {name: "Info Done"},
      Open: {name: "Open"},
      Closed: {name: "Closed"}
    },
    WaitingForUserMulti: {
      name: "Waiting For",
      type: entities.User.fieldType,
      multi: true
    }
  }
});
4 comments
Comment actions Permalink
        if(UserIsAmongWFIUsers()){
          changeIssueFieldValueFn_0();
          if(issue_1.fields["Waiting For"].isEmpty()){
            // Changing State to Open if no WFI Users left
            issue_1.fields['State'] = ctx.StateState.Open;
            //console.log("Block #2: State is changed to Open");
          } else {
            // Changing State from InfoDone to WaitingForInfo if there is WFI Users left
            issue_1.fields['State'] = ctx.StateState.WaitingForInfo;
            //console.log("Block #2: State is changed to WFI");
          }
        }

I did it differently, it works, but now another problem. If there is 1 user left in the "Waiting For Info" list, it cannot be deleted. The field can be empty.

0
Comment actions Permalink
issue_1.fields["Waiting For"].delete(ctx.currentUser);

I cannot delete a user if he is left alone in the "Waiting For Info" field. Why?

0
Comment actions Permalink
        // Remove current user from the WFI list
        const changeIssueFieldValueFn_0 = () => {
          // Count how many WFI users left
          var ucount = 0;
          issue_1.fields["Waiting For"].forEach(function(){
            ++ucount;
          });
          //console.log("Users left: " + ucount);
          // Deleting user from WFI list
          ucount == 1 ? issue_1.fields["Waiting For"] = null : issue_1.fields["Waiting For"].delete(ctx.currentUser);
          //console.log("Deleting user from WFI" + issue_1.fields["Waiting For"]);
        };

Now it works.

0
Comment actions Permalink

Hi! 

I'm Sergey from the YouTrack team. 

Glad to hear that you adjusted the rule so that it works now.

In general, though, you can utilize the workflow's editor console. Once you ensure that you attached the rule to the project and it has no visible errors, the next step to troubleshoot the rule is to add and inspect logs. I assume you converted your rule from the workflow constructor, so it has logging added by default. Examining the editor's console will help you see the logging output as well as errors. Based on these details, you can find and analyze the problematic parts of the rule. 

0

Please sign in to leave a comment.