Hi, the problem is that... If I'm doing render action like switching on issue tabs panels/processing workflow, some HTML elements of velocity will be duplicated:
Here is my web-resource, issue-tabpanel in atlassian-plugin.xml:
<web-resource key="my_plugin-resources" name="my_plugin Web Resources">
<dependency>com.atlassian.auiplugin:ajs</dependency>
<dependency>jira.webresources:jira-global</dependency>
<dependency>com.atlassian.auiplugin:aui-experimental-iconfont</dependency>
<dependency>com.atlassian.auiplugin:aui-table-sortable</dependency>
<dependency>com.atlassian.auiplugin:aui-inline-dialog2</dependency>
<dependency>com.atlassian.auiplugin:aui-select2</dependency>
<dependency>com.atlassian.auiplugin:aui-toggle</dependency>
<dependency>com.atlassian.auiplugin:aui-flag</dependency>
<dependency>com.atlassian.auiplugin:aui-help</dependency>
<dependency>com.atlassian.auiplugin:dialog2</dependency>
<dependency>com.atlassian.auiplugin:aui-dropdown2</dependency>
<dependency>com.atlassian.auiplugin:java.lang.String</dependency>
<resource type="download" name="my_plugin.css" location="css/my_plugin.css"/>
<resource type="download" name="my_plugin.js" location="js/my_plugin.js">
<property key="content-type" value="text/javascript"/>
</resource>
<resource type="download" name="images/" location="/images"/>
<context>atl.general</context>
<context>my_plugin</context>
</web-resource>
<issue-tabpanel key="jira-issue-tab-panel" name="jira Issue Tab Panel" i18n-name-key="jira-issue-tab-panel.name" class="com.my.plugin.jira.tabpanels.JiraIssueTabPanel">
<description key="jira-issue-tab-panel.description">The jira Issue Tab Panel Plugin</description>
<label key="jira-issue-tab-panel.label"/>
<resource type="velocity" name="view" location="templates/tabpanels/jira-issue-tab-panel.vm"/>
<order>200</order>
<sortable>true</sortable>
<supports-ajax-load>true</supports-ajax-load>
</issue-tabpanel>
velocity file jira-issue-tab-panel.vm:
<script type="text/javascript">
#include("js/my_plugin.js");
</script>
<div id="issue_guide_body">
<textarea id="async" style="display:none">$async</textarea>
<textarea id="issueId" style="display:none">$issue.getId()</textarea>
<div class="aui-group">
<div class="aui-item" style="width:10%;">
<button id="create-guide-dialog-show-button" class="aui-button aui-button-primary">TEST</button>
</div>
</div>
<section role="dialog" id="create-guide-dialog" class="aui-layer aui-dialog2 aui-dialog2-xlarge" aria-hidden="true">
<header class="aui-dialog2-header">
<h2 class="aui-dialog2-header-main"></h2>
<a class="aui-dialog2-header-close">
<span class="aui-icon aui-icon-small aui-iconfont-close-dialog">Close</span>
</a>
</header>
<div class="aui-dialog2-content">
<form id="create-guide" class="aui">
<div class="aui-group">
<div class="aui-item" style="width:50%;">
<select style="width:100%; max-width:100%;" id="select1" name="select1" placeholder="">
#foreach( $row in $select1 )
<option value="$row.getName()">$row.getName()</option>
#end
</select>
</div>
<div class="aui-item" style="width:50%;">
<select style="width:100%; max-width:100%;" id="select2" name="select2" placeholder="" multiple="">
#foreach( $row in $select2 )
<option value="$row.getName()">$row.getName()</option>
#end
</select>
</div>
</div>
</form>
</div>
<footer class="aui-dialog2-footer">
<div class="aui-dialog2-footer-actions">
<button id="create-guide-dialog-submit-button" class="aui-button aui-button-primary">OK</button>
<button id="create-guide-dialog-close-button" class="aui-button">close</button>
</div>
<div class="aui-dialog2-footer-hint"></div>
</footer>
</section>
</div>
javascript file my_plugin.js:
var counter = 0;
var initialised = false;
AJS.$(document).ready(function() {
var async = AJS.$("#async").val();
console.log("async:"+async);
if(async === "true"){
initialised = false;
}
console.log("initialised:"+initialised);
if(!initialised && AJS.$("#issueId").length !== 0){
initialised = true;
counter++;
console.log("counter:"+counter);
if(typeof AJS.$("#select1").data('select2') === typeof undefined)
AJS.$("#select1").auiSelect2();
if(typeof AJS.$("#select2").data('select2') === typeof undefined)
AJS.$("#select2").auiSelect2();
AJS.$("#create-guide-dialog-show-button").off('click');
AJS.$("#create-guide-dialog-show-button").on('click', function(e){
e.preventDefault();
AJS.dialog2("#create-guide-dialog").show();
});
}
});
java class com.my.plugin.jira.tabpanels.JiraIssueTabPanel:
package com.my.plugin.jira.tabpanels;
import com.atlassian.jira.plugin.issuetabpanel.*;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.my.plugin.dao.SelectADAO;
import com.my.plugin.dao.SelectBDAO;
import com.my.plugin.entity.*;
public class JiraIssueTabPanel extends AbstractIssueTabPanel2 implements IssueTabPanel2{
private static final Logger log = LoggerFactory.getLogger(JiraIssueTabPanel.class);
public JiraIssueTabPanel(){ }
@Override
public GetActionsReply getActions(GetActionsRequest request) {
final List<SelectA> select1 = SelectADAO.getSelectAByIDJira(request.issue().getId().toString());
final List<SelectB> select2 = SelectBDAO.getSelectBByIDJira(request.issue().getId().toString());
return GetActionsReply.create(new JiraIssueAction(request.isAsynchronous(), descriptor(), request.issue(), request.remoteUser(), select1, select2));
}
@Override
public ShowPanelReply showPanel(ShowPanelRequest request) {
boolean isShowing = true;
return ShowPanelReply.create(isShowing);
}
}
java action class com.my.plugin.jira.tabpanels.JiraIssueAction:
package com.my.plugin.jira.tabpanels;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.plugin.issuetabpanel.AbstractIssueAction;
import com.atlassian.jira.plugin.issuetabpanel.IssueTabPanelModuleDescriptor;
import java.util.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import com.atlassian.jira.template.VelocityTemplatingEngine;
import com.atlassian.jira.user.ApplicationUser;
import com.my.plugin.entity.*;
import static com.atlassian.jira.template.TemplateSources.file;
public class JiraIssueAction extends AbstractIssueAction {
private static final String PLUGIN_TEMPLATES = "templates/tabpanels/";
List<SelectA> select1 = new ArrayList<SelectA>();
List<SelectB> select2 = new ArrayList<SelectB>();
Issue issue;
ApplicationUser remoteUser;
Boolean async;
public JiraIssueAction(Boolean async, IssueTabPanelModuleDescriptor descriptor, Issue issue, ApplicationUser remoteUser, List<SelectA> select1, List<SelectB> select2){
super(descriptor);
this.async = async;
this.issue = issue;
this.remoteUser = remoteUser;
this.select1=select1;
this.select2=select2;
}
public Date getTimePerformed(){
return issue.getCreated();
}
protected void populateVelocityParams(Map params){
params.put("async",async);
params.put("issue",issue);
params.put("remoteUser",remoteUser);
params.put("select1",select1);
params.put("select2",select2);
}
public String getHtml() {
final String templateName = "jira-issue-tab-panel.vm";
final VelocityTemplatingEngine templatingEngine = ComponentAccessor.getComponent(VelocityTemplatingEngine.class);
final Map<String, Object> params = new HashMap(5);
populateVelocityParams(params);
return templatingEngine.render(file(PLUGIN_TEMPLATES + templateName)).applying(params).asHtml();
}
}
I had to use "initialised" variable to avoid some repeat case, but it still appeared problem...
JIRA version:
<jira.version>7.6.2</jira.version>
<amps.version>6.3.14</amps.version>
Need your advice and helps,
Sincerely
Hi @Chien-Hao Chen,
I see a few potential problems.
The first is that you're using two methods to load your script. The two methods I can see for your javascript being loaded:
Since you load the JavaScript code through your VM file, you can probably remove the same file from your web-resource. That will prevent the code from running twice on page load.
The second, and probably more likely cause of your problem: whenever you switch between issues on the view issue page, your issue panel will be re-rendered. That means creating your dialog HTML again, and including + running your JavaScript again. If you have previously opened a dialog, then switched issues, you will have two elements in your DOM with the same ID for the dialog. As a result, it is possible that your dialog's HTML contents is being created several times.
Before I could provide you with an idea of a guaranteed fix, you should check the following things when the problem occurs:
My guess as to how to fix the problem is that you will need to first detect when the view issue page's tabs are being rendered, then clean up any old dialog that was created for the previous issue view when that happens. Jira provides a global value called `JIRA.ViewIssueTabs.onTabReady` to help you here. Read these docs for more info: https://developer.atlassian.com/server/jira/platform/loading-issue-tab-panels-with-ajax/
Finally, this seems like a plugin development related question. We have a dedicated community for developers at https://community.developer.atlassian.com/. In future, if you ask questions there, they will likely be answered faster, since there are more developers watching those forums.
Good luck!
Daz
Online forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.