Come disabilitare alcuni pannelli nel dettaglio issue

A volte è necessario nascondere alcune parti della visualizzazione del dettaglio issue come ad esempio quello di connessione a Hipchat o quello degli SLA. Il problema è che alcuni di questi pannelli possono essere disabilitati SOLO globalmente mentre altri possono apparire o scomparire in base a determinate condizioni.

Hipchat

Prendiamo per esempio il pannello di Hipchat che appare in basso sulla destra nella schermata di dettaglio. In questo caso è necessario accedere alla lista dei plugins (add-ons) e cercare HipChat for JIRA, espandere la lista dei moduli e disabilitare hipchat-viewissue-panel. NON disabilitate l’intero plugin Hipchat ma SOLO il modulo. 

Knowledge Base

In questo caso il plugin da cercare è Service Desk Knowledge Base Plugin, espandere la lista dei moduli e cercare e disabilitare il modulo knowledgebase-issueview-panel.

Altro discorso vale per il pannello degli SLA e quello della Service Desk Request, sempre posizionati sulla destra della schermata di dettaglio. Scriptrunner ci viene in aiuto e senza dover disabilitare nessun plugin basta andare nella configurazione di Scriptrunner alla voce Script Fragment e scegliere la voce Hide system or plugin UI element.

In questo caso alla voce Hide what vanno inseriti i riferimenti a customer-portal-web-panel e sla-web-panel. Nel campo Conditions bisogna inserire (contro-intuitivamente) una condizione che risulti FALSE, per esempio se volessimo nascondere questi pannelli nel progetto con chiave DS dovremmo aggiungere:  jiraHelper.project?.key != “DS”

La lista degli oggetti che si possono nascondere è vastissima e dovrete solo cercare quello che fa al caso vostro.

Come disabilitare la funzione di ASSIGN in uno stato del workflow

Se fosse necessario disabilitare la funzionalità di “assign” in un determinato workflow è possibile farlo aggiungendo una “property” allo stato del workflow:

jira.permission.assign.denied = true

In questo modo, solo per quello stato, la funzione di “assign” viene disabilitata sia nell’editor inline sia il tasto nella barra delle operazioni che viene nascosto.

Inviare una mail da Scriptrunner utilizzando JETI (Email This Issue)

JETI è un plugin molto utile se si desidera personalizzare le mail inviate da JIRA. E’ possibile modificare sia le mail in ingresso che in uscita, è possibile attivare l’invio mal solo per certi contesti e aggiunge una post-function per inviare mail durante le transizioni.

Nel caso ci fisse bisogno di invocare un invio di una mail a certe condizioni è possibile (se non fosse possibile configurare dei context appositi) invocare JETI da scriptrunner in questo modo:

import com.atlassian.jira.component.ComponentAccessor
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.metainf.jira.plugin.emailissue.api.EmailService
import com.metainf.jira.plugin.emailissue.api.EmailDefinitionApi

@WithPlugin("com.metainf.jira.plugin.emailissue")

@PluginModule
EmailService emailService

emailService =
      ComponentAccessor.getOSGiComponentInstanceOfType(EmailService.class);
EmailDefinitionApi em = new EmailDefinitionApi()
em.issue = "CRE-7"
em.to = ["paolo@ibuildings.it"]
em.emailTemplate = 1

try{
    emailService.sendEmail(em)
  log.info("Sent")
}catch(Exception Ex){
  log.error(Ex.toString());
}

La documentazione riguardante le API  del plugin è reperibile a questo link

Aggiungere una nuova orgranizzazione a un progetto Service Desk

Con queste righe di codice potrete aggiungere una nuova organizzazione ad un progetto Service Desk

import com.atlassian.jira.component.ComponentAccessor 
  import com.atlassian.servicedesk.api.ServiceDeskManager 
  import com.atlassian.servicedesk.api.organization.CustomerOrganization 
  import com.atlassian.servicedesk.api.organization.OrganizationService 
  import com.atlassian.servicedesk.api.util.paging.SimplePagedRequest 
  import com.onresolve.scriptrunner.runner.customisers.WithPlugin 
 
  @WithPlugin ( "com.atlassian.servicedesk" ) 

  def serviceDeskManager = ComponentAccessor.  getOSGiComponentInstanceOfType (ServiceDeskManager) 
  def organisationService = ComponentAccessor.  getOSGiComponentInstanceOfType (OrganizationService) 

  def adminUser = ComponentAccessor.  userManager .getUserByKey( "admin" ) 
  def project = ComponentAccessor.  projectManager .getProjectByCurrentKey("CRE") 

  def serviceDeskProject = serviceDeskManager.getServiceDeskForProject(project)

  def newOrgParams = organisationService
        .newCreateBuilder()
        .name("opopop")
        .build()
  
  def org = organisationService.createOrganization(adminUser,newOrgParams)

  def organizationServiceDeskUpdateParameters = organisationService
        .newOrganizationServiceDeskUpdateParametersBuilder()
        .organization(org.right().get())
        .serviceDeskId(serviceDeskProject.right().get().serviceDeskId)
        .build()

  organisationService.addOrganizationToServiceDesk(adminUser,organizationServiceDeskUpdateParameters)

 

Come leggere da un file CSV allegato ad una Issue

Se vogliamo leggere il contenuto di un file CSV allegato ad una issue possiamo utilizzare queste poche righe di codice sfruttando la libreria già presente in jira “com.mindprod.csv.CSVReader”. Questa libreria contiene anche la parte delle routines di scrittura di un file CSV. In presenza di più files allegati basta aggiungere un “if” che scarti i files con estensione differente o con un nome file predefinito.

import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.util.AttachmentUtils
import com.atlassian.jira.util.PathUtils
import com.mindprod.csv.CSVReader
 
def issueManager = ComponentAccessor.getIssueManager()
MutableIssue issue = issueManager.getIssueObject("FFF-5")
 
def pathManager = ComponentAccessor.getAttachmentPathManager()
def attachmentManager = ComponentAccessor.getAttachmentManager()
 
attachmentManager.getAttachments(issue).each { attachment ->
    def filePath = PathUtils.joinPaths(pathManager.attachmentPath,
        issue.projectObject.key, issue.key, attachment.id.toString())
        log.info(attachment.filename)
    atFile = new File(filePath)
    File atFile = AttachmentUtils.getAttachmentFile(attachment);
    CSVReader reader = new CSVReader(new BufferedReader( new FileReader( atFile ) ));
    try {
        while(true) {
            String[] fields = reader.getAllFieldsInLine();
        }
    } catch ( EOFException e ) {
        reader.close();
    }
}

 

Come modificare il contenuto di un campo Select

Utilizzando i “Behaviours” è possibile modificare in tempo reale il contenuto di un campo select che potrebbe contenere opzioni che vanno eliminate o aggiunte a in particolari condizioni. Il seguente codice confronta i valori esistenti con un array di valori permessi e crea una variabile che contiene i solo i valori permessi e sovrascrive i valori del campo select. La riga contenente il “findAll” filtra il contenuto attuale e restituisce solo i valori che ne rispettano le condizioni.

import com.atlassian.jira.component.ComponentAccessor
import com.onresolve.jira.groovy.user.FieldBehaviours
import com.onresolve.jira.groovy.user.FormField
import com.atlassian.jira.component.ComponentAccessor
 
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def optionsManager = ComponentAccessor.getOptionsManager()
 
// Get a pointer to my select list field
def selectList = getFieldById("customfield_10304")
 
// Get access to the required custom field and options managers
def customField = customFieldManager.getCustomFieldObject(selectList.getFieldId())
def config = customField.getRelevantConfig(getIssueContext())
def options = optionsManager.getOptions(config)
def optionsMap = options.findAll {
  it.value in ["Complexity 1", "Complexity 2", "E"] // list of options you want to show
}.collectEntries {
  [
    (it.optionId.toString()): it.value
  ]
}
selectList.setFieldOptions(optionsMap)

 

Come impostare le dashboard dei propri gruppi di appartenenza come preferite

Con questo script che può essere creato all’interno di un Listener di Scriptrunner è possibile recuperare tutti i gruppi di un utente ed impostare come preferite tutte le dashboard che sono state condivise con i gruppi di utenti ai quali si appartiene.

Si può facilmente modificare il codice per modificare i criteri di impostazione con le condizioni volute.

L’evento al quale è collegato lo script è “UserAuthenticatedEvent”

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.portal.PortalPage
import com.atlassian.jira.portal.PortalPageManager
import com.atlassian.jira.user.ApplicationUser;
import com.atlassian.jira.favourites.FavouritesManager
import com.atlassian.jira.bc.portal.DefaultPortalPageService
import com.atlassian.jira.user.util.DefaultUserManager
import com.atlassian.crowd.event.user.UserAuthenticatedEvent

def favouritesManager = (FavouritesManager) ComponentAccessor.getOSGiComponentInstanceOfType(FavouritesManager.class)
def ppm = ComponentAccessor.getOSGiComponentInstanceOfType(com.atlassian.jira.portal.PortalPageManager)
def pps = ComponentAccessor.getOSGiComponentInstanceOfType(com.atlassian.jira.bc.portal.PortalPageService)

import com.atlassian.jira.event.AbstractEvent
import com.atlassian.jira.event.user.UserEvent

def newUserEvent = event as UserAuthenticatedEvent;
def appUser = newUserEvent.getUser(); 
ApplicationUser cu = ComponentAccessor.getUserManager().getUserByName(appUser.getName());

def gm = ComponentAccessor.getGroupManager()
def currentUserGroups = gm.getGroupNamesForUser(cu)
def allPortalPages = ppm.getAll()
List<PortalPage> dashboards = []
List<Boolean> present = []

allPortalPages.foreach { PortalPage a ->
  a.getPermissions().getPermissionSet().each { b ->
    def isGroup = b.getType().toString() == 'group'
    def group = b.getParam1()
    if (isGroup && currentUserGroups.contains(group)) {
  		dashboards.add(a)	
        present.add(pps.isFavourite(cu,a))
    }
  }
}

if (present.contains(true)) {
  log.info("Already set")
  	return true;
} else {
  dashboards.each { PortalPage a ->
    log.info(a.getName() + " was added");
    if (!pps.isFavourite(cu,a))
    	favouritesManager.addFavourite(cu, a)
  }
}

return true;

 

 

Come recuperare i campi presenti in uno screen

Per recuperare la lista dei custom fields presenti in uno screen si può usare il seguente codice

import com.atlassian.jira.issue.fields.screen.FieldScreenManager
def fieldManager = ComponentAccessor.getFieldManager();
def fieldScreenManager = ComponentAccessor.getComponent(FieldScreenManager.class);
def fieldScreens = fieldScreenManager.getFieldScreens()
def sc = fieldScreens.find { 
   /* in questo modo viene cercato lo screen per nome */
   it.name.startsWith("XXXXXX")
}
def rr = sc.getTab(0)
def a = rr.getFieldScreenLayoutItems().collect {
  it.getFieldId()
}

 

Resettare il progressivo delle issue di un progetto

Per resettare il progressivo presente nel nome delle issue di un progetto bisogna eseguire un paio di operazioni direttamente sul database.

Un plugin comodo e gratuito è “JIRA Home Directory And DB Browser” che permette, oltre che consultare il contenuto della home directory di JIRA direttamente dal portale, di eseguire comandi SQL sulle tabelle del DB. Dopo averlo installato vi si accede dalla sezione add-ons alla voce DB console.

Prima di continuare eseguite una query di controllo sulla tabella “moved_issue_key” e fate un backup del sistema.

I comandi da eseguire sono i seguenti:

UPDATE project SET pcounter=0 WHERE pkey='<chiave del progetto>';
DELETE FROM moved_issue_key WHERE old_issue_key like '<chiave del progetto>-%';

La cosa corretta sarebbe fermare JIRA e riavviarlo una volta eseguiti i comandi descritti.

 

Connessione diretta al database

Se fosse necessario collegarsi con groovy per query dirette al database è possibile farlo attraverso il seguente codice con drivers differenti a seconda del DB utilizzato

  • MYSQL (JIRA < 7.5): net.sourceforge.jtds.jdbc.Driver
  • MYSQL (JIRA > 7.5): com.mysql.jdbc.Driver
  • SQL Server: com.microsoft.sqlserver.jdbc.SQLServerDriver

In questo caso leggiamo dalla tabella del DB contenente la lista delle issue.

import groovy.sql.Sql
import java.sql.Driver
def driver = Class.forName('com.mysql.jdbc.Driver').newInstance() as Driver;
def props = new Properties();
props.setProperty("user", "username");
props.setProperty("password", "password") 
def conn = driver.connect("jdbc:mysql://localhost:3306/jiradb", props);
def sql = new Sql(conn):
try {
   sql.eachRow("select count(*) as num from jiraissue") {
        /* il vostro codice */
   }
} finally {
    sql.close()
    conn.close()
}