How to dynamically implement milestone bar?

I have to create a milestone bar which changes it's steps dynamically.


The resources I have is :

A look up table, "status_ref" containing statuses: "Pending", "Approved", "Ordered" and "Fulfilled", which represent the different statuses of a request.


We have two more statuses to deal with, those are "Canceled" and "Rejected" but those are not handled by the "status_ref". They are handled with boolean flags/columns, "is_canceled" and "is_rejected" in a "request" table containing all the requests.


I have the requirement of a milestone where first step should always be "Pending", then next possible steps shown are "Approved", then "Ordered" and then "Fulfilled". I am able to achieve this by simply using a query.

It should look like: "Pending">"Approved">"Ordered">Fulfilled".


But at any moment if request is "Pending", user can cancel the request. If it is canceled, then it should look like:


"Pending">"Canceled" (No further steps should be shown)


Or if it's Rejected then:


"Pending">"Rejected" (No further steps should be shown)


Now, the catch is, a request can be canceled after it is approved or ordered. Then milestone bar should look like:


"Pending">"Approved">"Canceled" (If Canceled after request is approved)
"Pending">"Approved">"Ordered">"Canceled" (If Canceled after request is ordered)


How can I achieve this pattern, please suggest any good dynamic approach to implement the solution.
Attaching few screenshots for better understanding showing how it should look like.
Any help is appreciated. Thanks

  Discussion posts and replies are publicly visible

Parents
  • +1
    Certified Lead Developer

    The logic might get a bit complicated but you should be able to handle this using if() conditionality in the code determining the "Steps" and "Active" parameters in your milestone field.  I'll attempt some brief pseudocode below to give a starting point for how you can do the logic tree:

    if(
      not(local!isCancelled),  /* any boolean value registering whether order was cancelled */
      
      /* non-cancelled logic: */
      a!milestoneField(
        steps: /* regular steps */
        active: /* current step */
      ),
      
      /* cancelled logic: */
      a!milestoneField(
        active: -1, /* shows all steps as completed */
        steps: {
          "Pending",
          if(local!isApproved, "Approved", {}),  /* show an entry for "approved" only if approved */
          if(local!isOrdered, "Ordered", {}), /* show an entry for "ordered" only if it was ordered */
          "Cancelled"
        }
      )
    )

  • Thanks . That worked well. But there's a little UI glitch I'm getting, it's creating extra space for null value.

    You can see there's extra space between "Approved" and "Canceled" for local!isOrdered as false. Any way to handle this extra space.

    Thanks

    Screenshot attached.

  • 0
    Certified Lead Developer
    in reply to varunkumarb0001

    I can't be 100% sure without seeing your code, but my guess is you've used a "null()" somewhere instead of an empty set ("{}") - which would create a "blank" entry on the milestone bar instead of ignoring that position.

  • a!milestoneField(
          active: - 1,
          steps: {
            index(
              local!statuses[1], /* Handling Pending */
              "StatusTypeName",
              {}
            ),
            if(
              not(rule!OSR_RULE_General_APN_isValueBlank(local!acceptedBy)),
              index(
                local!statuses[2], /* Handling Approved */
                "StatusTypeName",
                {}
              ),
              {}
            ),
            if(
              tointeger(
                local!statusTypeID
              ) = 5,
              index(
                local!statuses[3], /* Handling Ordered */
                "StatusTypeName",
                {}
              ),
              {}
            ),
            cons!OSR_TEXT_STATUS_CANCELED
          }
        )

    That's the code snippet, I'm using.

Reply
  • a!milestoneField(
          active: - 1,
          steps: {
            index(
              local!statuses[1], /* Handling Pending */
              "StatusTypeName",
              {}
            ),
            if(
              not(rule!OSR_RULE_General_APN_isValueBlank(local!acceptedBy)),
              index(
                local!statuses[2], /* Handling Approved */
                "StatusTypeName",
                {}
              ),
              {}
            ),
            if(
              tointeger(
                local!statusTypeID
              ) = 5,
              index(
                local!statuses[3], /* Handling Ordered */
                "StatusTypeName",
                {}
              ),
              {}
            ),
            cons!OSR_TEXT_STATUS_CANCELED
          }
        )

    That's the code snippet, I'm using.

Children