Incorrect client context for bitbucket.pullrequest.action client web items?

Using ?web.items in a pull request page, the bitbucket.pullrequest.action client web item shows that the client context should contain a pullRequest key and only that key. However, the following code returns request and currentUser as the only keys present in that context.

atlassian.xml client web item:

<client-web-item key="pr-item" name="Pull Request Action" weight="50" section="bitbucket.pullrequest.action">
      <label>My Pull Request Action</label>
      <condition class="java.path.to.conditions.classes.PrintContextCondition"/>
  </client-web-item>

PrintContextCondition.java:

@Override
public boolean shouldDisplay(Map<String, Object> context) {
	System.out.println("Printing context...");
	for (String key : context.keySet()) {
		System.out.println(key + ": " + context.get(key));
	}
	return True;
}

logs:

[INFO] [talledLocalContainer] Printing context...
[INFO] [talledLocalContainer] request: org.apache.catalina.connector.RequestFacade@61279cea
[INFO] [talledLocalContainer] currentUser: InternalNormalUser
{id=1, username=admin}

Is this a known bug or am I doing something wrong? I do see my client web item populating in the correct area of a pull request overview page.

1 Like

The properties shown are available from JS only. Because a client-web-item is often rendered many times per page load with different contexts, the clientside context is necessarily different from the server side one. In this particular case we could have inserted the pull request into the server side context, but didn’t. It would certainly be a solid improvement, but would prevent us from making an SPA between pull requests. We’d definitely consider it if you created a Suggestion at jira.atlassian.com.
As a workaround, if you implement a in JS, you’ll see the pullRequest property and can prevent the fragment rendering.
Good luck!

1 Like

Are there any built-in client-conditions that we can use like it was with conditions for web-items? For example, we used com.atlassian.bitbucket.web.conditions.PullRequestInState condition for our action button. And now we want to make this element a client-web-item. Do we need to implement the same condition functionality in js, or is there a ready-made solution?

There are no built-in conditions, but you can write your own fairly painlessly.

<client-condition>ctx.pullRequest.state == 'OPEN'</client-condition>
1 Like

Well, I see that checking pull request status is simple.
Unfortunately, my plugin logic is more complex.
We want to show a button depending on user’s branch permission and on plugins settings for repository (the settings are just true/false per repository). No such information is placed in client-condition context.

This is what we’ve implemented:

  1. <context-provider> that adds a list of repositories with “on” setting to context
  2. <client-condition> that checks, that current repo is in this this list
  3. <client-resource> tat laods a js script that waits for a button to appear, gets branch permissions by ajax call, and removes a button if user does not have enough permissions.

So, instead of several <condition>s we got a plenty of different xml elements, a context full of unnessessary data, and a permission check suseptible to network problems. Have we missed something? Can this functionality be implemented simplier?

@myxomopla, I had to do something similar as well only I didn’t use the context-provider. Instead I passed the repository to a custom rest endpoint and did all the condition evaluation on the server side. If you’re interested, our code is on Github.

I did open a feature request for the repository to be made available in the server side context here. More votes might get this more attention.

@explosivepyrounicorn
Such workaround was my first idea. It looks more straight than the mess i’ve done, but deprecated async: false in ajax call bothers me much :slight_smile:

Yeah this kind of async case could definitely be supported better. I created an issue for it a while ago as BSERV-7330. If that got a couple more Votes it wouldn’t hurt. :slight_smile: Or at least you could watch it to see if we implement it in the future.

The server-side repo seems useful as well to avoid the repo side of the problem for you, if not the branches side.

In the meantime, I probably wouldn’t recommend sending every repo through in the context - that might get bloated. Your #3 seems like what I’d expect (you’re doing it for branches now and could potentially change to check the repo and branch at the same time). But you might be better off doing it as the client-context-provider on your fragment. That way you can cache the responses and if the fragment is rerendered you’ll be able to render the right thing synchronously by passing the data to your template. Typically what we do with our internal plugins is initially render either nothing or a loading spinner, and then replace with the right UI when our REST request comes back with the info we need.

Best of luck!
Adam