
En este artículo, desarrollaremos un complemento que guardará la configuración del complemento en Jira. Utilizaremos las bibliotecas soy, requirejs, backbone js para mostrar la interfaz de usuario. Soy, requirejs, backbone js son bibliotecas integradas en Jira.
El propósito del artículo es mostrar cómo puede usar las herramientas integradas de Jira para desarrollar una interfaz de usuario.
El complemento desarrollado contendrá un módulo de trabajo web para guardar los parámetros del complemento en Jira. Los parámetros se ingresarán en dos pantallas (dos parámetros en cada pantalla). Además, los parámetros se empaquetarán en json, que se almacenará en Jira. El código fuente del complemento se puede encontrar
aquí .
Crea un esqueleto de plugin
Abra la terminal y ejecute el siguiente comando:
atlas-create-jira-plugin
Responderemos las preguntas en la terminal así:
Define value for groupId: : ru.matveev.alexey.jira.tutorial.webworkui Define value for artifactId: : webwork-soy-require-backbone Define value for version: 1.0.0-SNAPSHOT: : Define value for package: ru.matveev.alexey.jira.tutorial.webworkui: : Y: : Y
Realizar cambios en pom.xml
Después de crear el esqueleto del complemento, debe realizar cambios para que
atlassian-spring-scanner 2 funcione correctamente.
Instale la versión atlassian-spring-scanner en 2.0.0:
<atlassian.spring.scanner.version>2.0.0</atlassian.spring.scanner.version>
Cambie el alcance de la dependencia de anotación atlassian-spring-scanner-de compilación a proporcionada:
<dependency> <groupId>com.atlassian.plugin</groupId> <artifactId>atlassian-spring-scanner-annotation</artifactId> <version>${atlassian.spring.scanner.version}</version> <scope>provided</scope> </dependency>
Elimine la dependencia atlassian-spring-scanner-runtime.
Cree un servicio para recibir y guardar configuraciones de complementos
Primero, cree una interfaz para administrar la configuración del complemento.
src / main / java / ru / matveev / alexey / jira / tutorial / webworkui / api / PluginSettingService.java package ru.matveev.alexey.jira.tutorial.webworkui.api; public interface PluginSettingService { String getConfigJson(); void setConfigJson(String json); }
Ahora hagamos la implementación de la interfaz.
src / main / java / ru / matveev / alexey / jira / tutorial / webworkui / impl / PluginSettingServiceImpl.java package ru.matveev.alexey.jira.tutorial.webworkui.impl; import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport; import com.atlassian.sal.api.pluginsettings.PluginSettings; import com.atlassian.sal.api.pluginsettings.PluginSettingsFactory; import ru.matveev.alexey.jira.tutorial.webworkui.api.PluginSettingService; import javax.inject.Inject; import javax.inject.Named; @Named public class PluginSettingServiceImpl implements PluginSettingService { public final PluginSettings pluginSettings; private static final String PLUGIN_STORAGE_KEY = "ru.matveev.alexey.jira.tutorial.webworkui."; private static final String CONFIG_JSON = "configjson"; @Inject public PluginSettingServiceImpl(@ComponentImport PluginSettingsFactory pluginSettingsFactory) { this.pluginSettings = pluginSettingsFactory.createGlobalSettings(); } private void setSettingValue(String settingKey, String settingValue) { this.pluginSettings.put(PLUGIN_STORAGE_KEY + settingKey, settingValue != null?settingValue:""); } private String getSettingValue(String settingKey) { return pluginSettings.get(PLUGIN_STORAGE_KEY + settingKey) != null?pluginSettings.get(PLUGIN_STORAGE_KEY + settingKey).toString():""; } @Override public String getConfigJson() { return getSettingValue(CONFIG_JSON); } @Override public void setConfigJson(String json) { setSettingValue(CONFIG_JSON, json); } }
Los métodos getConfigJson y setConfigJson son responsables de recibir y guardar el parámetro en formato json.
Cree un trabajo web para administrar la configuración de complementos
Abra el terminal en la carpeta del complemento y ejecute el siguiente comando:
create-atlas-jira-plugin-module
Respondemos las preguntas en la terminal de la siguiente manera:
Choose a number (1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34): 31 Enter Plugin Module Name My Webwork Module: : Config Show Advanced Setup? (Y/y/N/n) N: : Y Module Key config: : webwork-config Module Description The Config Plugin: : i18n Name Key config.name: : i18n Description Key config.description: : Enter Action Classname MyActionClass: : ConfigWebwork Enter Package Name ru.matveev.alexey.jira.tutorial.webworkui.jira.webwork: :Enter Alias ConfigWebwork: : Enter View Name success: : success.soy Enter Template Path /templates/webwork-config/configwebwork/success.soy.vm: : /templates/webwork-config/configwebwork/success.soy Add Another View? (Y/y/N/n) N: : N Add Another Action? (Y/y/N/n) N: : N Add Another Plugin Module? (Y/y/N/n) N: : N
Como resultado, se creará el archivo src / main / java / ru / matveev / alexey / jira / tutorial / webworkui / jira / webwork / ConfigWebwork.java. Este archivo necesita ser cambiado así:
src / main / java / ru / matveev / alexey / jira / tutorial / webworkui / jira / webwork / ConfigWebwork.java package ru.matveev.alexey.jira.tutorial.webworkui.jira.webwork; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.atlassian.jira.web.action.JiraWebActionSupport; import ru.matveev.alexey.jira.tutorial.webworkui.api.PluginSettingService; import javax.inject.Inject; public class ConfigWebwork extends JiraWebActionSupport { private static final Logger log = LoggerFactory.getLogger(ConfigWebwork.class); private final PluginSettingService pluginSettingService; private String configJson; @Inject public ConfigWebwork(PluginSettingService pluginSettingService) { this.pluginSettingService = pluginSettingService; } @Override public String execute() throws Exception { super.execute(); return SUCCESS; } public void doSave() { pluginSettingService.setConfigJson(configJson); } @ActionViewData public String getConfigJson() { return pluginSettingService.getConfigJson().isEmpty()?"{}":pluginSettingService.getConfigJson(); } public void setConfigJson(String json) { this.configJson = json; } }
La anotación @ActionViewData es necesaria para que el parámetro configJson esté disponible en la plantilla de soja.
Crear una sección web y un elemento web
Hemos agregado trabajo web. Ahora agregue el elemento del menú desde el cual se iniciará el trabajo web.
Abra la terminal y ejecute el siguiente comando:
create-atlas-jira-plugin-module
Respondemos las preguntas de la siguiente manera:
Choose a number (1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34): 30 Enter Plugin Module Name My Web Section: : Webwork Config Section Enter Location (eg system.admin/mynewsection): admin_plugins_menu Show Advanced Setup? (Y/y/N/n) N: : N Add Another Plugin Module? (Y/y/N/n) N: : Y Choose a number (1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34): 25 Enter Plugin Module Name My Web Item: : Webwork Config Item Enter Section (eg system.admin/globalsettings): admin_plugins_menu/webwork-config-section Enter Link URL (eg /secure/CreateIssue!default.jspa): /secure/ConfigWebwork.jspa? Show Advanced Setup? (Y/y/N/n) N: : N Add Another Plugin Module? (Y/y/N/n) N: : N
Como resultado, creamos un elemento de menú en la página Complementos.
Crea una plantilla de soja
Los detalles sobre las plantillas de soya se pueden encontrar
aquí .
Crearemos un archivo
src / main / resources / templates / webwork-config / configwebwork / success.soy.
src / main / resources / templates / webwork-config / configwebwork / success.soy {namespace webwork.config} /** * This template is needed for drawing the formview. */ {template .formview} {@param configJson: string} {webResourceManager_requireResource('ru.matveev.alexey.jira.tutorial.webworkui.webwork-soy-require-backbone:webwork-soy-require-backbone-resources')} <html> <head> <meta charset="utf-8"/> <meta name="decorator" content="atl.admin"> <meta name="admin.active.section" content="admin_plugins_menu/telegram-config-section"> <meta name="admin.active.tab" content="telegram-general-config-item"> <title>my page page</title> </head> <body> <div id="container"> <form class="aui" action="ConfigWebwork!save.jspa" method="POST"> <div class="field-group"> <label for="configJson">Json</label> <input class="text long-field" type="text" id="configJson" name="configJson" placeholder="Json String" value="{$configJson}"> <div class="description">the configJson Parameter</div> </div> <div class="buttons-container"> <div class="buttons"> <input class="button submit" type="submit" value="Save" id="config-save-button"> <a class="cancel" href="#">Cancel</a> </div> </div> </form> </div> </body> </html> {/template}
En el archivo atlassian-plugin.xml, agregue un enlace a la plantilla de soya creada en la etiqueta de recursos web:
<resource type="soy" name="webwork-config" location="/templates/webwork-config/configwebwork/success.soy"/>
Ahora haremos cambios en atlassian-plugin.xml para que cuando accedamos al trabajo web, se muestre la plantilla de soja creada:
<view name="success" type="soy">:webwork-soy-require-backbone-resources/webwork.config.formview</view>
webwork-soy-require-backbone-resources es el atributo de nombre en la etiqueta de recursos web, donde agregamos un enlace a nuestra plantilla de soja.
webwork.config.formview: espacio de nombres y nombre de la plantilla del archivo de soja.
Complemento de prueba
Abra el terminal en la carpeta del complemento y ejecute el siguiente comando:
atlas-run
Después de que Jira se inicie, vaya al navegador usando el siguiente enlace:
localhost : 2990 / jira / secure / ConfigWebwork.jspa
La pantalla se verá así:

Puede intentar ingresar datos en el campo Json y guardar. El trabajo web funciona.
Ahora debemos asegurarnos de que haya dos pantallas para completar los parámetros, y en la última pantalla, el botón Guardar debe convertir todos los parámetros al formato json y guardarlos en la configuración del complemento.
Para controlar la lógica de moverse por pantallas y convertir parámetros al formato json, utilizaremos backbone js. Puedes leer sobre backbone js
aquí .
Crear un modelo de red troncal
src / main / resources / js / webwork-config-model.jsdefine ('webwork / config / model', [
'jquery',
columna vertebral
subrayado
], función ($, Backbone, _) {
var WebConfigModel = Backbone.Model.extend ({
valores predeterminados: {
parámetro1: '',
parámetro2: '',
parámetro3: '',
parámetro4: ''
}
});
volver {
Modelo: WebConfigModel
};
})
Para que el modelo esté disponible al cargar la plantilla de soja, el archivo con el modelo debe agregarse a atlassian-plugin.xml en la etiqueta de recursos web:
<resource type="download" name="webwork-config-model.js" location="/js/webwork-config-model.js"/>
Crear una vista de red troncal
Escribí comentarios en el código para puntos importantes.
src / main / resources / js / webwork-config-view.js// define es una directiva requirejs y define el modelo como un módulo webwork / config / view. Esto nos permite definir dependencias en otros archivos del modelo.
define ('webwork / config / view', [
'jquery',
columna vertebral
subrayado
], función ($, Backbone, _) {
"Uso estricto";
var AppView = Backbone.View.extend ({
eventos: {
"Haga clic en # config-save-button": "saveConfig",
"Haga clic en # botón siguiente": "botón siguiente",
"Haga clic en el botón # atrás": "prevButton"
},
// función que funciona con el botón Guardar. Guarda los parámetros de la pantalla al modelo y los convierte al formato json
saveConfig: function () {
this.model.set ("parámetro3", $ ("# parámetro3"). val ());
this.model.set ("parameter4", $ ("# parameter4"). val ());
$ ("# configJson"). val (JSON.stringify (this.model));
},
// función que funciona con el botón Siguiente en la primera pantalla. Guarda los parámetros de la primera pantalla en el modelo y dibuja una segunda pantalla
nextButton: function () {
this.model.set ("parámetro1", $ ("# parámetro1"). val ());
this.model.set ("parámetro2", $ ("# parámetro2"). val ());
plantilla var = webwork.config.page2 ({configJson: $ ("# configJson"). val (), parámetro3: this.model.get ('parámetro3'), parámetro4: this.model.get ('parámetro4')} );
$ ("# contenedor"). replaceWith (plantilla);
$ ("# configJson"). val (JSON.stringify (this.model));
},
// función que funciona con el botón Atrás en la segunda pantalla. Guarda los parámetros de la segunda pantalla en el modelo y dibuja la primera pantalla
prevButton: function () {
this.model.set ("parámetro3", $ ("# parámetro3"). val ());
this.model.set ("parameter4", $ ("# parameter4"). val ());
plantilla var = webwork.config.page1 ({configJson: $ ("# configJson"). val (), parámetro1: this.model.get ('parámetro1'), parámetro2: this.model.get ('parámetro2')} );
$ ("# contenedor"). replaceWith (plantilla);
$ ("# configJson"). val (JSON.stringify (this.model));
},
initialize: function () {
this.render ();
},
render: function () {
plantilla var = webwork.config.page1 ({configJson: $ ("# configJson"). val (), parámetro1: this.model.get ('parámetro1'), parámetro2: this.model.get ('parámetro2')} );
$ ("# contenedor"). replaceWith (plantilla);
},
// este es un enlace al contenedor principal. La vista capturará todos los eventos de los elementos debajo de este elemento.
el: '#maincontainer'
});
volver {
Vista: AppView
};
})
Para que la vista esté disponible al cargar la plantilla de soja, el archivo con la vista debe agregarse a atlassian-plugin.xml en la etiqueta de recursos web:
<resource type="download" name="webwork-config-view.js" location="/js/webwork-config-view.js"/>
Cree un archivo js para personalizar el modelo de red troncal y ver
src / main / resources / js / webwork-soy-require-backbone.jsrequerir ([
'webwork / config / view',
'webwork / config / model',
'jquery',
columna vertebral
subrayado
], function (webworkConfigView, webworkConfigModel, $, Backbone, _) {
var webworkConfigModel = nuevo webworkConfigModel.Model (JSON.parse ($ ("# configJson"). val ()));
var actionsView = new webworkConfigView.View ({model: webworkConfigModel});
})
Nuestro archivo js usa requirejs. La directiva require le permite asegurarse de que el archivo se descargará solo después de descargar todas las dependencias. Definimos las siguientes dependencias para nuestro archivo: webwork / config / view, webwork / config / model, query, backbone, subrayado.
Agregue los parámetros necesarios para que las plantillas de soya funcionen.
En la etiqueta de recursos web en el archivo atlassian-plugin.xml, agregue:
<transformation extension="soy"> <transformer key="soyTransformer"/> </transformation> <resource name="success-soy.js" type="download" location="/templates/webwork-config/configwebwork/success.soy"/>
Estos parámetros le permiten acceder a la plantilla de soja en archivos js.
Haz cambios al éxito.
Agregué comentarios a puntos importantes
src / main / resources / templates / webwork-config / configwebwork / success.soy {namespace webwork.config} /** * webwork. json . page1. , json backbone model. */ {template .formview} {@param configJson: string} {webResourceManager_requireResource('ru.matveev.alexey.jira.tutorial.webworkui.webwork-soy-require-backbone:webwork-soy-require-backbone-resources')} <html> <head> <meta charset="utf-8"/> <meta name="decorator" content="atl.admin"> <meta name="admin.active.section" content="admin_plugins_menu/telegram-config-section"> <meta name="admin.active.tab" content="telegram-general-config-item"> <title>my page page</title> </head> <body> <div id="maincontainer"> <div id="container"> <input class="text long-field hidden" type="text" id="configJson" name="configJson" placeholder="Json String" value="{$configJson}"> </div> </div> </body> </html> {/template} /** * . parameter1 parameter2. */ {template .page1} {@param configJson: string} {@param parameter1: string} {@param parameter2: string} <div id="container"> <form class="aui"> <div class="field-group"> <label for="parameter1">Parameter 1</label> <input class="text long-field" type="text" id="parameter1" name="parameter1" placeholder="Parameter1 value" value="{$parameter1}"> <div class="description">Value of Parameter 1</div> </div> <div class="field-group"> <label for="parameter2">Parameter 2</label> <input class="text long-field" type="text" id="parameter2" name="parameter2" placeholder="Parameter2 value" value="{$parameter2}"> <div class="description">Value of Parameter 2</div> </div> <div class="field-group"> <input class="text long-field hidden" type="text" id="configJson" name="configJson" placeholder="Json String" value="{$configJson}"> </div> <div class="buttons-container"> <div class="buttons"> <a class="cancel" href="#">Cancel</a> <input class="button submit" type="submit" value="Next" id="next-button"> </div> </div> </form> </div> {/template} /** * . parameter3 parameter4. */ {template .page2} {@param configJson: string} {@param parameter3: string} {@param parameter4: string} <div id="container"> <form class="aui" action="ConfigWebwork!save.jspa" method="POST"> <div class="field-group"> <label for="parameter1">Parameter 3</label> <input class="text long-field" type="text" id="parameter3" name="parameter3" placeholder="Parameter3 value" value="{$parameter3}"> <div class="description">Value of Parameter 3</div> </div> <div class="field-group"> <label for="parameter4">Parameter 4</label> <input class="text long-field" type="text" id="parameter4" name="parameter4" placeholder="Parameter4 value" value="{$parameter4}"> <div class="description">Value of Parameter 4</div> </div> <div class="field-group"> <input class="text long-field hidden" type="text" id="configJson" name="configJson" placeholder="Json String" value="{$configJson}"> </div> <div class="buttons-container"> <div class="buttons"> <input class="button submit" type="submit" value="Back" id="back-button"> <input class="button submit" type="submit" value="Save" id="config-save-button"> </div> </div> </form> </div> {/template}
Probar la aplicación
Abra el terminal en la carpeta del complemento y ejecute:
atlas-run
Después de que Jira se inicie, abra el navegador usando el enlace:
http://localhost:2990/jira/secure/ConfigWebwork.jspa
Verá la siguiente pantalla:

Complete los parámetros y haga clic en el botón Siguiente. Aparecerá la siguiente pantalla:

Complete los parámetros 3 y 4 y haga clic en el botón Guardar. Los parámetros se guardarán en formato Json. Puede hacer clic en el botón Atrás y accederá a la primera pantalla.
Nuestro complemento funciona.