Atlassian Forge Jira Dashboard Gadget - No "entryPoint" for edit mode - jira

I am working on a Custom UI Dashboard Gadget using the forge documentation here. The documentation refers to the context.extension.entryPoint. I can retrieve and see the context, and context.extension in the values returned by view.getContext() but there is no entryPoint key in the returned object.
How should I determine whether the dashboard is in edit mode so that I can configure my gadget?
Relevant code is.
import { view } from '#forge/bridge';
const context = await view.getContext()
console.info(JSON.stringify(context))

The Atlassian documentation says "With a Custom UI, you can define the same resource for viewing and editing your dashboard gadget" and then goes on to describe the code I posted above for retrieving the context. I have been unable to use the same component for configuring the dashboard because there is no 'edit' information in the context. The only solution I have managed to find is to create a separate component for configuring the dashboard and thus specifying the below manifest, which points at a separate component for editing.
jira:dashboardGadget:
...
resource: dashboard-quality
resolver:
function: resolver
edit:
resource: dashboard-quality-edit
This seems to work and it isn't much additional effort, so I am going to accept this as an answer to my own Q, even though it doesn't really solve it based on my original intent.

Related

How to set the description of a JIRA Workflow Validator?

I'm working on a simple JIRA Server plugin that will prevent a transition from occurring if a certain custom field has not been set. I have created a new workflow validator with atlas-create-jira-plugin-module and tailored the validate function to fit my needs. Strangely, when I add this new validator to a transition via the workflow editor, it appears in the list of validations with the wrong description. It is showing the description from the default condition, "Only users with Resolve Issues" permission can execute this transition".
I've been following along with this tutorial: https://developer.atlassian.com/server/jira/platform/creating-workflow-extensions/
I also came across this similar tutorial: https://www.j-tricks.com/tutorials/workflow-validator
In my atlassian-plugin.xml I made sure to define a "view" velocity resource:
<workflow-validator key="custom-field-is-set-validator" name="Custom Field Is Set Validator" i18n-name-key="custom-field-is-set-validator.name" class="com.ngc.jira.plugins.workflow.CustomFieldIsSetValidatorFactory">
<description key="custom-field-is-set-validator.description">Validation to require that a custom field be given a value.</description>
<validator-class>com.ngc.jira.plugins.workflow.CustomFieldIsSetValidator</validator-class>
<resource type="velocity" name="view" location="templates/validators/custom-field-is-set-validator.vm"/>
<resource type="velocity" name="input-parameters" location="templates/validators/custom-field-is-set-validator-input.vm"/>
<resource type="velocity" name="edit-parameters" location="templates/validators/custom-field-is-set-validator-input.vm"/>
</workflow-validator>
And the contents of custom-field-is-set-validator.vm are as follows:
Only if the custom field <strong>$field</strong> has be set.
As a sanity check, I created a workflow condition and applied my velocity (vm) resource as the view template for it. It shows up correctly within this context!
However, when I try to use the same velocity resource for my workflow validator, the admin page still displays the validator as "Only users with Resolve Issues permission can execute this transition" instead of using my description.
What am I missing? Thanks!
Screenshot showing the built-in condition
Screenshot showing my validator that is wrongly appearing as the same condition
I wrote an O'Reilly book Practical Jira Plugins back in 2011 that has a validator example. The source for this is at https://bitbucket.org/mdoar/practical-jira-plugins/src/default/ (and the book is Out There).
But frankly these days I'd use ScriptRunner, JMWE or other plugins that let you write custom workflow things. But don't let that stop you learning it! Good luck
It turns out, I had copied/pasted a piece of code from my workflow condition that needed to be tweaked for a workflow validator. I was trying to cast to a ConditionDescriptor when I should have been casting to a ValidatorDescriptor:
Bad:
if (!(descriptor instanceof ConditionDescriptor)) {
throw new IllegalArgumentException("Descriptor must be a ConditionDescriptor.");
}
ConditionDescriptor conditionDescriptor = (ConditionDescriptor) descriptor;
Good:
if (!(descriptor instanceof ValidatorDescriptor)) {
throw new IllegalArgumentException("Descriptor must be a ValidatorDescriptor.");
}
ValidatorDescriptor validatorDescriptor = (ValidatorDescriptor) descriptor;
Pretty neat that instead of completely breaking my plugin, it ended up displaying a different description altogether. ;)

Multiple Adobe Analytic tools in Adobe DTM - how do I only have one fire at a time?

I have multiple instances of Adobe Analytics in the same Adobe DTM web property. They all go to different report suites. I'd like to create a page load rule so that the data is only reported to one report suite for any given page. So far the page load rules that I have created are causing the AA data to report to all of the report suites. Does anyone have any idea to get them to only fire to one at a time?
Thanks,
Mike
It is possible to set DTM to suppress the call for an event based rule or direct call rule but currently it is not possible to do it with a page load rule within the DTM built-in interface.
Some things you can do:
1) Combine your Adobe Analytics instances into a single instance. Is there a particular reason you are using multiple instances of Adobe Analytics? I know you mentioned they are for separate report suites, but are they also for separate Adobe Analytics instances altogether? If not, is it because they are completely separate implementations with different variables and logic assigned for them? If the only thing different between them is report suite id, then you should combine them and write some logic to pop relevant report suite id(s) for s.account.
2) Make use of s.abort to suppress the calls. If your code version is H25.3+ or you are using AppMeasurement then you can set s.abort to true to make the next Adobe Analytics request (s.t or s.tl call) be cancelled. Note that this may only be feasible if your instances are all using separate namespaces.. if you are just outputting several instances of code all under the same namespace, you will have issues. Also, if you are doing that, then you may also have issues as far as variables carrying over to other instances. But in any case, basically within your page load rule you'd add a rule condition where criteria is Data:Custom and then you'd write js logic to determine which one(s) you don't want to pop and set [namespace].abort=true; for each of them. Then return true at the end to make sure the condition is always true.
Or, you can set s.abort=true; within the Custom Page Code section for each Adobe Analytics instance you want to suppress in the page load rule. There are various other methods for popping s.abort but hopefully you get the picture. Which one is best just depends on how all your stuff is actually setup.
3) Pop the Adobe Analytics tags as a regular tag instead of a Tool. Remove them as a tool and put them as a Javascript / Third Pary Tag within the page load rule. This includes the core lib code and anything else you may have in the Tool config section. This also means outputting the "trigger" (s.t call). Make a separate one for each one and then you can make conditions for them to pop.
To add to Crayon's answer, you can also choose a custom code implementation in the Library Management section of the tool configuration settings. You will have to paste in the s_code contents and check the box that says "Set report suites using custom code below"
Then, you can use whatever logic you want to set a variable in the code that directs data to the report suites.
if(document.location.href == "http://www.mypage1.com"){
s_account = "rsid_1";
}else{...}
To add to Brett's answer - with rare exception, I let Adobe manage the analytics file. However, you can use the customize page code section within the Adobe Analytics tool configuration to deploy plugins or set the report suite ID dynamically. Here's an example I commonly use:
var suiteid;
var enviro;
var getURL = window.location.href
// Set RSID based on URL
if (getURL.indexOf('myURL.com') != -1)
{
suiteid = 'rsidproduction';
s.linkInternalFilters = 'javascript:,mailto:,tel:,' + window.location.host;
enviro = 'prod';
}
else
{
suiteid = 'rsidstaging';
s.linkInternalFilters = 'javascript:,mailto:,tel:,' + window.location.host;
enviro = 'dev';
}
s.account = suiteid;
This is an easy way to dynamically change the RSID and keep the analytics file managed by Adobe. I also blogged about this here: Managing your RISD Dynamically

Set the Visitor ID in Adobe Analytics through DTM

I'm trying to set the Visitor ID in Adobe Analytics through DTM.
Above the s_code I have:
var visitor = new Visitor("xxxx")
visitor.trackingServer = "xxx.xx.xx.omtrdc.net"
I've created a data element where the legacy code used to call the
Visitor.getInstance("xxxx");
and set the Visitor ID to %Visitor ID%
That's not working however, and my visitor ID is always just set to %Visitor ID% and obviously not reading any values. I'd really appreciate any input that someone can give me.
Thanks,
Mike
The Visitor ID pops s.visitorID and is in general related to visitor id, but is not the same as s.visitor which is what gets popped for the VisitorAPI integration. DTM does not currently have a built-in field for the s.visitor variable, so you will have to set it yourself within the config, either in the Library Management code editor (assuming you are opting to c/p the core lib and not the "Managed by Adobe" option) or else in the Custom Page Code section.
Since you are popping it in a data layer first, you can reference the data layer like this:
s.visitor = _satellite.getVar('Visitor ID');
NOTE: A separate potential issue you may have is with whether or not the Visitor object is available for your data element. Since data elements are the first thing to be evaluated by DTM, you will need to ensure that the VisitorAPI.js library is output before your top page DTM script include.
If this is a problem for you, or if you are wanting to host VisitorAPI.js within DTM, then you may need to adjust where you are popping that stuff. For example, place the VisitorAPI core code above the custom code as the first stuff within the data element, before:
var visitor = new Visitor("xxxx") visitor.trackingServer = "xxx.xx.xx.omtrdc.net
Or, don't use the data element at all. Instead, put the VisitorAPI code within the Adobe Analytics custom code or core lib section and pop all that stuff (aboove the s.visitor assignment). Or a number of other methods; point is, VisitorAPI stuff must be loaded before the data element can make use of it, same as it must be loaded before Adobe Analytics can make use of it.
So DTM is changing pretty fast and furious right now. They have a "Marketing Cloud Service ID" that works well. Before I used that, however, I did find a way to fix the code. Crayon Violent was right, as usual, that the problem was that the script wasn't available yet. I fixed this by putting the following code in between the VisitorAPI.js and the AppMeasurement stuff in the DTM managed library.
var aA = new AppMeasurement();
aA.visitorNamespace="companyname";
aA.visitor = Visitor.getInstance("companyname");
In addition, there were also some issues using my localhost for testing while trying to see if I had this correct or not. If you are having issues and think you have it correct, it may be worthwhile to elevate it to a different environment.

Displaying how often an issue has been reopen in JIRA

I'm currently running a fairly out-of-the-box JIRA setup that is live and being used.
Now I'm at a point where I would like a custom field in each bug that will display the total amount of times and issue/bug has been reopened.
There is a plugin (https://answers.atlassian.com/questions/19665/how-to-count-based-on-status-jira) that does something similar, however, I am looking for a solution that doesn't require purchasing a third-party plugin (OPS doesn't like plugins).
I've searched forums high and low and was unable to even find a good starting point. Your help is always appreciated. Thanks in advance!
EDIT: Current JIRA version: 5.2
Create a custom field for counting the times an issue was opened, and set it's default value to one. Then use the Behaviours Plugin to add validation script to the transitions you wish to count. In the validation script, increment the custom field and return true. should be something like:
FormField formComponent = getFieldById(fieldChanged)
FormField formUserField = getFieldByName("UserFieldA"
formUserField.setFormValue(Integer.valueOf(formUserField.getFormValue()) + 1)
If you're having trouble coding that have a look here or ask here.
An easier way would be to attack a post-function to the re-open transition using
Jira Scripting Suite and use it to increment the field, but it doesn't support Jira 5.2 yet.
If you don't want to use any plugins, you can use Webhooks attached to the re-open workflow transition that will post to an URL , which in turn, will connect back using the REST API and increment that field.
A Custom field holds some information (metric, counter, misc. info, etc.) but it is not logic by itself. So the problem here is that in order to increment a (custom) field you will have to have some logic doing that. So you're left with three options:
Use the plugin you're talking about
Custom-build a plugin for this
Use a custom-built external application utilizing the REST API that polls for changes on issues and when it detects "Reopenings" and increments the custom field's value.
Manually assign this field (not really an option)
So at the end there aren't that many options that do not require resouces - development or purchasing some plugin. Usually it's best to buy a plugin because you're also buying support with that. However beware that if the plugin is not developed by Atlassian there is the possibility that it may not support future JIRA versions or it may not be compatible right after a new JIRA version release.
My solution is to add the post-function to the 'Reopen' transition with the following code (it assumes you have Script Runner plugin installed and enabled; also you have to add custom field 'Reopen count' to the corresponding view screen):
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.ModifiedValue
def componentManager = ComponentManager.getInstance()
def customFieldManager = componentManager.getCustomFieldManager()
def reopenCount = customFieldManager.getCustomFieldObjects(issue).find {it.name == 'Reopen count'}
def changeHolder = new DefaultIssueChangeHolder();
def reopenCountValue = issue.getCustomFieldValue(reopenCount)
if(reopenCountValue == null) reopenCountValue = 0.0d
reopenCount.updateValue(
null,
issue,
new ModifiedValue(
reopenCountValue,
++reopenCountValue
),
changeHolder
);

Django admin/doc/views/ all blank or broken

I'm trying to use Django's built-in admin docs feature to make writing templates easier. Supposedly if you go to /admin/docs/views you should get documentation for every view in your application. I see a list, but none of the links work:
-) Any view listed that's related to my application just goes to a blank page with nothing but the name of the view as a header.
-) The views related to admin all give me Django 404 errors when I click on them, except those that are related to the docs itself. The docs-related links also give me blank pages. (i.e. clicking /admin/doc/filters gives a blank page with nothing but "django.contrib.admindocs.views.template_filter_index" as a title, but clicking /admin/auth/user gives me a Django 404 error
The 404 errors lead me to suspect my URLconf is wrong, but all I did was uncomment the built-in lines. The relevant sections read:
# Uncomment the admin/doc line below to enable admin documentation:
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
(r'^admin/', include(admin.site.urls)),
And I have no idea what to make of the blank pages. Do I need to provide some extra meta information somewhere, like I know you need to provide the get_absolute_url on models for some of the admin features to work right?
Even if no one knows the answer, any documentation on the admin docs feature would be useful -- I've been Google all over (and searching StackOverflow) and this feature seems very little-documented.
Thanks!
You need to add 'django.contrib.admindocs' to your INSTALLED_APPS in settings.py. It should already be there and commented out. Though it would be nice if the comment in urls.py mentioned it ... Source.
I've never looked at the views admin doc pages before -- I've never had a need to. B4ut you're right, they seem to be -- lacking in potential features.
If you give your views functions docstrings (documentation), that content will appear on your "blank pages".
Most -- no, all -- of the admin sites views are actually decorated member methods of admin.sites.AdminSite. I looked around, and a view of mine which uses a decorator also suffers from the 404.
The view responsible for view details starts:
def view_detail(request, view):
if not utils.docutils_is_available:
return missing_docutils_page(request)
mod, func = urlresolvers.get_mod_func(view)
try:
view_func = getattr(import_module(mod), func)
except (ImportError, AttributeError):
raise Http404
title, body, metadata = utils.parse_docstring(view_func.__doc__)
...
You can see it tries to import the view to get info from it; if the view is actually a decorator (which probably used an internal function to wrap the real view), it won't be able to import it. eg, if you do from django.contrib.admin.sites import index in a django shell, you'll get an ImportError, whereas django.contrib.admin.site.index (note the singular site) is a:
<bound method AdminSite.index of <django.contrib.admin.sites.AdminSite object at 0x...>>
Further, that last line in my snippet seems to indicate that there's a capability for finer control over what shows up on those pages, if you care to figure out the template that util.parse_docstring uses.

Resources