пятница, 21 февраля 2025 г.

Задача: Создать ссылку, аналогичную Assignee to me для поля Reviewer (которое у нас имеется). Т.к. я не смог найти корректные зацепки за блок People - я пришел к альтернативному решению. Размещение кнопки справа, вверху, над блоком People. При нажатии - текущий пользователь будет назначен ревьювером.

image
Итоговый вариант

Из инструментов будет один ScriptRunner.

Код для Condition фрагмента я предварительно размещаю в отдельном файле (делаю для удобства хранения кода в гите). Вы же можете размещать скрипт inline.

package Projects.FSDK.UiFragments

import com.atlassian.jira.component.ComponentAccessor

def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def issueKey = issue.key 
def issue = ComponentAccessor.getIssueManager().getIssueObject(issueKey)

def projectKey = issue.getProjectObject().getKey()
if (projectKey != "FSDK") {
    return false
}

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def reviewerField = customFieldManager.getCustomFieldObjectsByName("Reviewer")

if (reviewerField) {
    def reviewer = issue.getCustomFieldValue(reviewerField)
    return reviewer != currentUser
}

return true

Условие достаточно простое. Я ограничиваю отображение кнопки (фрагмента) в рамках тестового проекта FSDK. И дополнительное условие: если ревьювер уже имеется - кнопку тоже скрываю.

Теперь создаем сам фрагмент.

Нас интересует Custom web item.

Секция размещения: jira.issue.tools

Key: set-reviewer-button

Текст: I'm a Reviewer

Weight: 1

Condition: выбираем наш заготовленный код

Поле Do what: Do noting - you will use javascript to bind an action

Link (сейчас обясню): https://jira.instans.ru/rest/scriptrunner/latest/custom/setMeReviewer?issueKey=${issue.key}

Наш действие кнопки необходимо как то обрабатывать. Поэтому мы осуществим вызов нашего REST Endpoint, который создадим ниже. А пока - это это лишь ссылка заготовка, для окончательной реализации.

Сам фрагмент готов. Сохранив его - мы уже можем увидеть кнопку, в нужном проекте.

Т.к. ссылка пока ведет в никуда - приступим к созданию REST Endpoint.

REST Endpoint

Как я уже писал выше - нажатие на кнопку необходимо обрабатывать. Можно было бы усложнить и взаимодействовать с Ajax, чтобы нажатие было "бесшовным". Но я решил не усложнять и просто написать обработчик нажатия.

Итак, код для REST Endpoint я так же размещаю в отдельном файле:

package Projects.FSDK.RESTEndpoints


import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import groovy.transform.BaseScript
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.UpdateIssueRequest

@BaseScript CustomEndpointDelegate delegate

setMeReviewer(groups: ['administrators','allUsers']) { MultivaluedMap queryParams ->

    def issueKey = queryParams.getFirst("issueKey") as String
    def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
    
    def issue = ComponentAccessor.getIssueManager().getIssueObject(issueKey)

    def customFieldManager = ComponentAccessor.getCustomFieldManager()
    def reviewerField = customFieldManager.getCustomFieldObjectsByName("Reviewer").first()

    if (reviewerField) {
        issue.setCustomFieldValue(reviewerField, currentUser)

        def updateRequest = UpdateIssueRequest.builder()
            .eventDispatchOption(EventDispatchOption.ISSUE_UPDATED) 
            .sendMail(true) 
            .build()

        ComponentAccessor.getIssueManager().updateIssue(currentUser, issue, updateRequest)

        def redirectUrl = "https://jira.instans.ru/browse/${issueKey}"
        return Response.status(302).location(URI.create(redirectUrl)).build()
    } else {
        return Response.status(400).type(MediaType.APPLICATION_JSON).entity([status: 'error', message: 'Reviewer field not found']).build()
    }
}

А потом просто создаю REST Endpoint и указываю этот файл, в качестве исполнительного.

Ключевые комментарии по файлу:

  • setMeReviewer(groups: ['administrators','allUsers']) - где setMeReviewer - это то самое окончание для нашей ссылки, которое мы указывали в веб-фрагменте. а группы - это перечисление локальных групп, которым доступно выполнение этого REST.

  • Мы могли бы просто выполнять необходимое нам действие, но в варианте по умолчанию - мы получим ответ JSON об успешном исполнении. Я же предпочел, чтобы пользователь видел ту же страницу issue. Поэтому прибегнул к редиректу по коду 302.

  • В ссылке веб-фрагмента, в конце ссылки - я передаю аргумент, в виде ключа issue.

Собственно всё. Эти простые действия позволяют нам получить функциональную кнопку, в нужном месте ;)

четверг, 8 апреля 2021 г.

JIRA & SIL: Gadget - Как узнать, где используется локальная группа


Однажды... мне надоело смотреть на непонятное кол-во групп и я бы с радостью их грохнул. Потому как в них уже давно никто не добавляется. 

Но прежде чем это сделать - неплохо было бы выяснить - а где они используются. 

Jira в этом случае - не столь информативна. Поэтому я решил воспользоваться возможностями SIL и написать что-то универсальное, что подошло бы к любому инстансу (в рамках стандартных SQL запросов)

вторник, 2 февраля 2021 г.

JIRA & SQL: Сбросить счетчик задач

В одной из ранних статей я уже писал о том, какие команды требуется выполнить для того, чтобы сбросить счетчик задач. 

Иногда, когда готовишь проект, приходится создавать тестовые задачи. Для того, чтобы потом отдать проект в чистом виде и пользователь сам создал свою ПЕРВУЮ задачу - необходимо сбросить счетчик задач. Ведь если вы удалите Issue - следующая всёравно будет создана с номером, который следует за уже ранее существующими Issue. 

Но чтобы не лезть каждый раз в БД и выполнять команды из оснастки\менеджера БД - я решил использовать SIL и его базовый функционал.

четверг, 9 апреля 2020 г.

SIL: как показать сообщение live fields каждому пользователю всего один раз?

Иногда возникает потребность показать информационное сообщение, но ВСЕГО ОДИН РАЗ - каждому пользователю, а не при любом движении или обновлении экрана. 
Это можно реализовать с помощью Live Fields.
Концепт реализации прост. Мы просто будем записывать во временный файл тех, кому мы сообщение показывали. 
Если смысл ясен - можете попробовать сделать его сами, а ниже решение.

среда, 1 апреля 2020 г.

Справочник с автокомплитом и возможностью добавления значения, с помощью Power Database Fields PRO™

Не знаю как у вас, а у меня многие бы вопросы закрывались решением по кейсу: 
Сделать поле, в котором бы можно было вводить данные и если ранее они уже было введены - то предлагать варианты, для автозаполнения, а если значения не было - добавить его в некий "справочник" значений. 
Таким образом, это поле должно работать как метки или компоненты. 
Решение не совсем стандартное и не описано в документации, поэтому делюсь им тут. 
Нам потребуется аддон Power Database Fields PRO™

воскресенье, 22 марта 2020 г.

SIL: Reports Charts. График выполненных задач по неделям

Если вам, как и мне, потребовался график, который покажет кол-во выполненных задач, группируя их по неделям, то эта статья как раз для вас (smile)
На выходе мы получим следующий гаджет на дашборде:

четверг, 27 февраля 2020 г.

JIRA: JQL выбрать все задачи, за 2 дня ДО Due Date

Например, нам необходимо отслеживать наступление Due Date и подсвечивать задачи, у которых Due Date наступит в течении 2х дней
Сразу такой фильтр в голову почему-то не пришел, поэтому я запишу его решение тут, чтобы в следующий раз голову не ломать (smile) 
duedate <= 2d AND duedate >startOfDay()

Кому разобраться хочется: