Hi, I need help getting started. The documentation and tutorials seem outdated and don't work. I managed to get "Hello World" to work and I added some UserPrefs, but the "edit" button on the dashboard does nothing. I tried to use some #-directives and they just render as text in the gadget.
I would really appreciate some help getting started in the right direction. A simple tutorial for creating a gadget that works in JIRA 6.4 or something. I just need a config screen, and to query JIRA with JQL (I assume). My gadget is going to draw a graph using Google charts (but that's the easy part).
Please help me!
Community moderators have prevented the ability to post new answers.
Hi Test
Recently I faced the same problem and only way to get working addon was digging the code of existing atlassian's gadgets and it cost me some time and nerves. I still plan to write the tutorial but as always short on time. For now hare are code snippets to give you a quick start.
in atlassian-plugin.xml you need to have entry for gadget and probably some JavaScript file:
<!-- In case you want to store labels in your-gadget.properties or support i18n --> <resource type="i18n" name="i18n" location="your-gadget" /> <web-resource key="your-gadget-resources" name="your-gadget-resources"> <resource type="download" name="your-gadget.js" location="your-gadget.js"> <property key="content-type" value="text/javascript" /> </resource> </web-resource> <gadget location="your-gadget.xml" key="your-gadget-gadget" name="your-gadget-gadget" />
your-gadget.xml should look like:
<?xml version="1.0" encoding="UTF-8" ?> <Module> <ModulePrefs title="__MSG_your-gadget.name__" description="__MSG_your-gadget.description__" author="vkrupach"> <Optional feature="gadget-directory"> <Param name="categories"> JIRA </Param> </Optional> <Require feature="setprefs" /> <Require feature="dynamic-height" /> <Require feature="views" /> <Require feature="oauthpopup" /> #oauth #supportedLocales("gadget.common,your-gadget") </ModulePrefs> <UserPref name="setting1" datatype="hidden" default_value="" /> <UserPref name="setting2" datatype="hidden" default_value="" /> <UserPref name="isConfigured" datatype="hidden" default_value="false" /> <UserPref name="refresh" datatype="hidden" default_value="false" /> <Content type="html" view="profile,canvas,home"><![CDATA[ #requireResource("com.atlassian.jira.gadgets:g-filter-results") <script type="text/javascript"> var contextPath = "__ATLASSIAN_BASE_URL__"; </script> #requireResource("atlassian-plugin.key:your-gadget-resources") #includeResources() ]]></Content> </Module>
setting1 and setting2 are config fields specific for the gadget.
#requireResource("atlassian-plugin.key:your-gadget-resources") includes your JavaScript. atlassian-plugin.key should be replaced by key you have in atlassian-plugin.xml: <atlassian-plugin key="..."
And main JavaScript "magic part":
(function() { var drawCahrt = function(view, setting1, setting2) { // your code here ... }; AJS.Gadget({ baseUrl : contextPath, // we set it in your-gadget.xml config : { onResizeAdjustHeight : true, descriptor : function(args) { var gadget = this; return { // I need to validate my setting1 and setting2 on server so there I have java custom REST code. I think you can remove the "action" property. action : "/rest/your-gadget/latest/validate", theme : function() { // copied this from the "source" addon. Not sure if I need it. if (gadgets.window.getViewportDimensions().width < 450) { return "gdt top-label"; } else { return "gdt"; } }(), // initialize settings field. AJS.gadget.fields.nowConfigured() is for update interval. fields : [ { userpref : "setting1", label : gadget.getMsg("your-gadget.config.setting1"), type : "text", value : gadget.getPref("setting1") }, { userpref : "setting2", label : gadget.getMsg("your-gadget.config.setting2"), type : "text", value : gadget.getPref("setting2") }, AJS.gadget.fields.nowConfigured() ] }; } }, view : { onResizeAdjustHeight : true, enableReload : true, template : function(args) { var gadget = this; this.getView().empty(); var view = AJS.$(this.getView()); drawCahrt(view, args.setting1FromServer, args.setting2FromServer); // JRADEV-3464: Resizing the gadget after a considerable timeout to make sure bottom isn't cutoff setTimeout(function() { gadget.resize(); }, 500); }, // Based on my setting1 and setting2 I do some work on the server. By configuring "args" section we ask the gadget to call 2 custom REST methods passing setting1 and setting2 as arguments. Results returned by the REST are stored as setting1FromServer and setting2FromServer and I pass them to my "do job javascript code". You can skip the "args" if you do not need to do anything on the server and just pull the settings via gadgets.util.unescapeString(this.getPref("setting1"). args : [ { key : "setting1FromServer", ajaxOptions : function() { return { url : "/rest/your-gadget/latest/setting1", data : { setting1 : gadgets.util.unescapeString(this.getPref("setting1")) } }; } }, { key : "setting2FromServer", ajaxOptions : function() { return { url : "/rest/your-gadget/latest/setting2", data : { setting2 : gadgets.util.unescapeString(this.getPref("setting2")) } }; } } ] } }); })();
Hi Volodymyr, Many thanks for your code. I will try to make sense of it and let you know if it works. The first thing I noticed is that you have atlassian-plugin.xml where as I only have gadget.xml. When I add the gadget to JIRA via URL it points to the gadget.xml so where does the plugin.xml come in?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello! Looks like you are developing standalone gadget and I put sample for gadget packaged as atlassian plugin. More info here: https://developer.atlassian.com/display/GADGETS/Packaging+your+Gadget+as+an+Atlassian+Plugin. Anyway I guess that JavaScript AJS.Gadget structure is the same for the gadget. Please update us with your status!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi, I see that #-directives are not supported in the stand alone gadget, but I don't see how to include the required resources without them. I get AJS is undefined error in the console. I would prefer to get the stand alone to work because it sounds like it should be a lot simpler than making a plugin.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi! Try to include scripts via <script> tag or start prototyping javascript directly in the gadget.xml
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
AJS.Gadget is part of JIRA so it's undefined for the standalone gadget. The proven way is to search for working standalone gadget and look into sources.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi, I am really struggling to find a working stand alone gadget that has any of the features I need (config edit screen and querying JIRA). The best I could find is this tutorial which gives me OAuth error: consumer_key_unknown https://developer.atlassian.com/jiradev/jira-platform/gadgets/tutorial-writing-a-jql-standalone-gadget (and I don't have confluence).
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yiou can check workaround from nagy: https://answers.atlassian.com/questions/122001/oauth-consumerkeyunknown-when-using-gadget-in-jira
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I tried nagy's work around and eventually got it to work by removing the /jira/ from the url, but I think I actually need to access the REST API to retrieve stuff like hours billed. I gave up trying to get the stand alone gadget to work. It is so poorly documented and It seems it's just not possible to create anything functional from the info that's available online. I have now installed the Atlassian Plugin SDK. I guess I am just going to have to build a full gadget plugin.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
My guess is that oauth does not work for the stand alone gadgets. Anyone can confirm/disconfirm this?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
It's too late and it's just a guess but maybe it will help someone: I guess that "OAuth error: consumer_key_unknown" (please see Test Testington, Mar 27, 2015) is caused by not configured or missconfigured Application Link. Step 7 of the tutotial shows "Oauth Administration: page that was replaced by Application Links in newer JIRA's.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi again. It's true that I did not have an application link, however in my case I am building a JIRA dashboard gadget which should get data from JIRA. It doesn't seem possible to create an application link from JIRA to JIRA. The tutorial is for a confluence gadget and therefore needs an application link to connect to JIRA.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Test! I am a bit confused :-). If it's a standalone gadget, then it's not a part of a JIRA and rather independent web application that can be hosted under separate domain. Please correct me if I am wrong.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I may be wrong (I am very new to all this), but a stand alone gadget is just an xml file (containing xml, html, css, js) which you host on a separate domain and then you load it into JIRA. JIRA caches it and renders the cached version in an iframe on the dashboard. I am not sure how the OAuth should work between JIRA and the cached gadget.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I am not sure but guess that it should be under separate server. Here are some trails (https://developer.atlassian.com/about/templates-for-writing-tutorials/template-for-standalone-gadget-tutorial#TemplateforStandaloneGadgetTutorial-Step3.MaketheGadgetAvailableonaServer): Because you are developing a standalone gadget, you can host your gadget specification on any server that will make it available to a dashboard. Anyway this area is very poorly documented.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Has anything recently changed? I used this tutorial last year, and wrote a gadget; that used this technique to call Object/functions in secondary files, which worked as follows
#requireResource("com.my-org.atla.plugin.my-plugin:cool-plugin") #includeResources() <script type="text/javascript"> CoolPlugin.setURL("__ATLASSIAN_BASE_URL__"); </script>
Then CoolPlugin did the AJS.Gadget work in a function, along with setURL and UI stuff.
Around oct/nov i updated SDK etc, and now the same code, no longer sees CoolPlugin object as valid.
Appreciated!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
"gadget" plugin module is not supported since JIRA 7.1.x and you have to write
"
dashboard-item" plugin module.
You may have a look on Universal Gadget for JIRA plugin and it's sources. This project demonstrates how to write common gadgets for JIRA Server and JIRA Cloud.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Wow, thanks man. I have a really tough time finding anything up to date for gadget/plugin doc/sdk examples. I'll do some reading. I can probably get it working again; but really want/need it to load from secondary resource files, and not all inline in CDATA block. i'm sure i'm not alone there
thanks Volodymyr!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
thanks for the sample code, its very useful.
However, i'm still struggling to use the 'replacement mode', as the reference to gadget.xml seems to not work.
i've loaded up your entire source, in my local - and it works. So i might just re-factor the entire thing to be standalone mode, using your code base as my starting point / editing. Kinda lame
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
gadget.xml is not needed/supported for new "
dashboard-item" plugin module. Just use mine sample as start point or try to find some dashboard-item in JIRA sources.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
yup - will do - thanks again dude . I've wasted so many hours bouncing-around Atlassian non-existent, 4 year stale docs, or vaguely updated new docs. Your projects a god-send.
Cheers!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Googled more and finally found a way to store the preferences for standalone gadgets.
You will need to handle showing/hiding of the Configuration screen on you own (i.e. onclick for Edit menu option to show and hide on save) and your configuration options will be rather HTML elements than custom UserPref elements supported by the packaged JIRA gedget plugins.
Other way is to include all scripts that are pushed to the gadget plugins by #requireResource("com.atlassian.jira.gadgets:common") veocity macro, so you will have all javascripts provided by JIRA for plugin gadgets (and can use AJS.Gadget), but it does not look as a right approach.
Why this is not documented and we have to dig the info by pieces from the whole internet ?
<?xml version="1.0" encoding="UTF-8" ?> <Module> <ModulePrefs title="TEST: Save prefs" height="100"> <Require feature="dynamic-height"/> <Require feature="setprefs"/> </ModulePrefs> <UserPref name="server" display_name="Server" datatype="string" default_value="http://arrogantbastard:8090/jira"/> <UserPref name="prefVal" display_name="FILTERVAL" datatype="hidden" /> <Content type="html"> <![CDATA[ <input type="text" id="txtInput"><input type="button" id="btnInput" value="Save pref"> <div id="divTest"></div> <script type="text/javascript"> (function() { var prefs; gadgets.util.registerOnLoadHandler(function() { prefs = new gadgets.Prefs(); document.getElementById("divTest").innerHTML = "Current prefVal == \""+prefs.getString("prefVal")+"\"<br>"; }); function log(text) { if(console) console.log(text); } document.getElementById("txtInput").onkeyup = function(e) { var keycode; if(window.event) keycode = window.event.keyCode; else if(e) keycode = e.which; if(keycode == 13) savePref(this.value); } document.getElementById("btnInput").onclick = function() { savePref(document.getElementById("txtInput").value); } function savePref(prefValue) { //console.log(prefs); var d = document.getElementById("divTest"); d.innerHTML = "Current prefVal == \""+prefs.getString("prefVal")+"\"<br>"; d.innerHTML += "Saving new setting... (prefVal = \""+prefValue+"\")<br>"; //console.log("prefVal = \""+prefs.getString("prefVal")+"\". Saving new setting..."); prefs.set("prefVal", prefValue); d.innerHTML += "Setting saved. prefVal == \""+prefs.getString("prefVal")+"\"<br>"; //console.log("Setting saved.... Filter (prefs) @savePref = "+prefs.getString("prefVal")); //console.log(" "); } })(); </script> ]]> </Content> </Module>
The code snippet is from here: https://ecosystem.atlassian.net/browse/AG-162
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for the suggestions. I'll check them out when I have time and let you know.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello Test again .
Your last comment initiated a background thread in my mind that revealed to me that you are right and for simple gadget that access only JIRA REST we do not need any oauth. I mistakenly thought that standalone gadgets are served from the original server, but as I see they are parsed and served from the JIRA. Not sure if they are cashed since in my dev environment my local changes are picked up right away.
So I got "Hello word" from google gadgets tutorial, added ajax to call\ first JIRA REST method, put it under local apache, added to my dev JIRA through "Add Gadget to Directory" and it actually works.
Here is my quick dirty code:
<?xml version="1.0" encoding="UTF-8" ?> <Module> <ModulePrefs title="hello world example" /> <Content type="html"> <![CDATA[ <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> <script> $.ajax({ url: "http://192.168.1.10:2990/jira/rest/api/2/application-properties", }) .done(function( msg ) { alert( "Data msg: " + msg ); }); </script> Hello, world! ]]> </Content> </Module>
Probably that's what you had at very begining .
Missing part is the Config options but I see that JIRA pushed to the iframe some javascripts that actually somehow should support storing of the configs. Can someone please contribute how to work with configs in Standalone gadgets.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Community moderators have prevented the ability to post new answers.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.