使用Issue Navigator显示许多Jira问题

时间:2014-06-06 02:06:13

标签: post cookies jira jira-plugin

My question is similar to "Displaying Jira issues using Issue Navigator"但我担心的是,有时我的问题列表很长,如果我的链接比URL的最大长度短,则只为用户提供指向问题导航器的链接。

还有其他方法吗?饼干?发布数据?也许以编程方式动态创建和共享过滤器,并返回使用此过滤器的问题导航器的链接? (但在某些时候我想删除这些过滤器,所以我不会有这么多人躺着。)

我确实有JQL查询来获取相同的问题列表,但是运行时间非常长(非常长),我的代码已经完成了查找结果的工作 - 我没有&#39 ; t希望用户等待两次同样的事情(一次我生成时髦的图形化servlet视图,第二次想要在Issue Navigator中看到相同的结果)。

1 个答案:

答案 0 :(得分:0)

实现此目的的最简单方法是确保将问题列表缓存在某个应用程序组件中的某个位置。每个单独的问题列表都应该通过您自己定义的唯一ID(下面的magicKey)来识别。

然后,您将编写自己的JQL函数,该函数通过该魔术键查找预先计算的问题列表,然后将问题列表转换为Issue Navigator所需的格式。

buildUriEncodedJqlQuery()方法可用于动态创建此类示例JQL查询。例如,如果魔术键是1234,它将产生此JQL查询:issue in myJqlFunction(1234)

然后,您将向用户提供如下所示的网址:

String url = "/secure/IssueNavigator.jspa?mode=hide&reset=true&jqlQuery=" + MyJqlFunction.buildUriEncodedJqlQuery(magicKey);

最终结果是用户将被置于问题导航器中,查看您的代码提供的问题列表。

此代码还专门阻止用户将JQL函数保存为已保存过滤器的一部分,因为它假定应用程序中的问题缓存不是永久性的。如果这不正确,您将需要清空sanitiseOperand部分。

在atlassian-plugins.xml中:

<jql-function key="myJqlFunction" name="My JQL Function" 
              class="com.mycompany.MyJqlFunction">
</jql-function>

JQL功能:

import com.atlassian.crowd.embedded.api.User;
import com.atlassian.jira.JiraDataType;
import com.atlassian.jira.JiraDataTypes;
import com.atlassian.jira.jql.operand.QueryLiteral;
import com.atlassian.jira.jql.query.QueryCreationContext;
import com.atlassian.jira.plugin.jql.function.ClauseSanitisingJqlFunction;
import com.atlassian.jira.plugin.jql.function.JqlFunction;
import com.atlassian.jira.plugin.jql.function.JqlFunctionModuleDescriptor;
import com.atlassian.jira.util.MessageSet;
import com.atlassian.jira.util.MessageSetImpl;
import com.atlassian.jira.util.NotNull;
import com.atlassian.query.clause.TerminalClause;
import com.atlassian.query.operand.FunctionOperand;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MyJqlFunction implements JqlFunction, ClauseSanitisingJqlFunction
{
    private static final String JQL_FUNCTION_NAME = "myJqlFunctionName";
    private static final int JQL_FUNCTION_MIN_ARG_COUNT = 1;
    private static final int JQL_FUNCTION_MAGIC_KEY_INDEX = 0;

    public MyJqlFunction()
    {
        // inject your app's other components here
    }

    @Override
    public void init(@NotNull JqlFunctionModuleDescriptor moduleDescriptor)
    {
    }

    @Override
    public JiraDataType getDataType()
    {
        return JiraDataTypes.ISSUE;
    }

    @Override
    public String getFunctionName()
    {
        return JQL_FUNCTION_NAME;
    }

    @Override
    public int getMinimumNumberOfExpectedArguments()
    {
        return JQL_FUNCTION_MIN_ARG_COUNT;
    }

    @Override
    public boolean isList()
    {
        return true;
    }

    /**
     * This function generates a URL-escaped JQL query that corresponds to the supplied magic key.
     * 
     * @param magicKey
     * @return
     */
    public static String buildUriEncodedJqlQuery(String magicKey)
    {
        return "issue%20in%20" + JQL_FUNCTION_NAME + "(%22"
                + magicKey + "%22%)";
    }

    @Override
    public List<QueryLiteral> getValues(@NotNull QueryCreationContext queryCreationContext,
                                        @NotNull FunctionOperand operand,
                                        @NotNull TerminalClause terminalClause)
    {
        User searchUser = queryCreationContext.getUser();

        MessageSet messages = new MessageSetImpl();

        List<QueryLiteral> values = internalGetValues(searchUser,
                operand,
                terminalClause,
                messages,
                !queryCreationContext.isSecurityOverriden());

        return values;
    }


    private List<QueryLiteral> internalGetValues(@NotNull User searchUser,
                                                 @NotNull FunctionOperand operand,
                                                 @NotNull TerminalClause terminalClause,
                                                 @NotNull MessageSet messages,
                                                 @NotNull Boolean checkSecurity)
    {
        List<QueryLiteral> result = new ArrayList<QueryLiteral>();

        if (searchUser==null)
        {
            // handle anon user
        }

        List<String> args = operand.getArgs();

        if (wasSanitised(args))
        {
            messages.addErrorMessage("this function can't be used as part of a saved filter etc");
            return result;
        }

        if (args.size() < getMinimumNumberOfExpectedArguments())
        {
            messages.addErrorMessage("too few arguments, etc");
            return result;
        }

        final String magicKey = args.get(JQL_FUNCTION_MAGIC_KEY_INDEX);


        // You need to implement this part yourself! This is where you use the supplied
        // magicKey to fetch a list of issues from your own internal data source.

        List<String> myIssueKeys = myCache.get(magicKey);

        for (String id : myIssueKeys)
        {
            result.add(new QueryLiteral(operand, id));
        }

        return result;
    }

    @Override
    public MessageSet validate(User searcher, @NotNull FunctionOperand operand, @NotNull TerminalClause terminalClause)
    {
        MessageSet messages = new MessageSetImpl();
        internalGetValues(searcher, operand, terminalClause, messages, true);
        return messages;
    }

    @Override
    public FunctionOperand sanitiseOperand(User paramUser, @NotNull FunctionOperand operand)
    {
        // prevent the user from saving this as a filter, since the results are presumed to be dynamic

        return new FunctionOperand(operand.getName(), Arrays.asList(""));
    }

    private boolean wasSanitised(List<String> args)
    {
        return (args.size() == 0 || args.get(JQL_FUNCTION_MAGIC_KEY_INDEX).isEmpty());
    }
}