JIRA layout per-project - jira

Would it be possible to use a project-specific stylesheet for JIRA projects?
For example, if I would like to include project X in an iframe, I'd like to hide the logo and possibly the JIRA toolbar - for specific user groups for example (it's only for viewing purpose, it is not a security feature)
Granted that I'd have to implement this myself (through the webservice api for example) - are there templates for the standard issue page?
Thanks in advance!

There is a (currently undocumented) plugin point in JIRA for inserting top navigation components, <top-navigation>.
You can use this plugin point to add your own navigation bar, and perhaps hide the normal bar using an inline CSS stylesheet. The following example triggers this behavior by using a ?hideit=true query parameter, which is the simplest way to approach the "embed in iframe" problem. You could make that "sticky" by storing it in a session or cookie.
Once you have created a plugin that plugins into the <top-navigation>, hiding the top bar is simple. Here is a velocity script that does it:
#if ($hideHeaderHack)
<style>
\#header {display:none;}
</style>
HIDDEN (remove this message eventually)
#else
NORMAL (remove this message eventually)
#end
To create such a plugin, use the Atlassian Plugin SDK (use atlas-create-jira-plugin). Your atlassian-plugin.xml should look like:
<atlassian-plugin key="${project.groupId}.${project.artifactId}" name="${project.name}" plugins-version="2">
<plugin-info>
<description>${project.description}</description>
<version>${project.version}</version>
<vendor name="${project.organization.name}" url="${project.organization.url}" />
</plugin-info>
<top-navigation key="standard-navigation-top"
name="Tigerblood"
class="com.madbean.topnavhack.TopNav" state='enabled'>
<resource type="velocity" name="view" location="topnav.vm"/>
<order>5</order>
</top-navigation>
</atlassian-plugin>
Your top-navigation implementation class (called com.madbean.topnavhack.TopNav above) should look like:
public class TopNav implements PluggableTopNavigation {
private TopNavigationModuleDescriptor descriptor;
public void init(TopNavigationModuleDescriptor descriptor)
{
this.descriptor = descriptor;
}
public String getHtml(HttpServletRequest request) {
Map<String,Object> params = new HashMap<String, Object>();
params.put("hideHeaderHack", "true".equals(request.getParameter("hideit")));
return descriptor.getTopNavigationHtml(request, params);
}
}
Your plugin will be laid out something like:
./pom.xml
./src/main/java/com/madbean/topnavhack/TopNav.java
./src/main/resources/atlassian-plugin.xml
./src/main/resources/topnav.vm
Disclaimer I work for Atlassian as a developer in the JIRA team.

I don't believe this functionality is exposed directly, and you don't state what JIRA version you are using, but in 4.x in \atlassian-jira\includes\decorators there is a file called bodytop.jsp the has the following fragment that renders the top level navigation and toolbar elements:
// Render all the top nav plugins
for (Iterator iterator = topNavPlugins.iterator(); iterator.hasNext();) {
TopNavigationModuleDescriptor topNavModuleDescriptor = (TopNavigationModuleDescriptor) iterator.next();
PluggableTopNavigation pluggableTopNavigation = (PluggableTopNavigation) topNavModuleDescriptor.getModule();
%>
<%= pluggableTopNavigation.getHtml(request) %>
<%
}
%>
If you wanted to you could create a version of the dashboard rendering jsp that calls a modified bodytop.jsp that renders none of the usual nav elements.

I would be tempted to write a basic plugin to do this.
Take a look at http://confluence.atlassian.com/display/JIRA/Web+Resource+Plugin+Module
If you have yet to write a jira plugin, now might be the time to try it out http://confluence.atlassian.com/display/DEVNET/Developing+your+Plugin+using+the+Atlassian+Plugin+SDK .

I'm currently running Jira 4.2.2 and wrote a plugin that implements PluggableTopNavigation for a custom navigation bar. Unfortunately, this functionality, as detailed in the awarded question, is now depreciated.
My plugin added a div to the top of the Jira header that created a nice menu for use with our development pages. The source of the menu was hard-coded into the plugin and located as a static menu.html file on our server for sharing across different pages.
Since I'd have to completely redesign the plugin for Jira 5.2, I started searching for different ways to re-implement the menu. Here's what I settled on. It's not pretty, but it makes it so you don't have to write a plugin.
Change your announcement banner (quickly get there by typing 'gg', then search for announcement banner) to the following:
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery.get("http://path.to.server/menu.html", function(data){
jQuery("#header").prepend('<nav class="global" role="navigation">'+data+'</nav>');
jQuery("#top-level-id-of-navbar a").css("color", "white")
});
});
</script>
Replace the menu.html link with your own link. The color of the header was inherited by the links in my menu, so I had to change them back to white after inserting the html page.
The result looks identical to Jira 4.2.2, so I'm happy.

Related

Export NextJS project as a module

I'm looking for a little guidance and suggestions here. My attempts and theories will be at the bottom.
I have a NextJS project from which I want to export the top level component (essentially the entry file) so that I can use it as a preview in my dashboard.
The nextjs project is very simple. For the sake of simplicity, let's imagine that all it renders is a colored <h1>Hello world</h1>. Then in my dashboard, I want to render a cellphone with my NextJS component embedded and then from the dashboard change the color of the text, as a way to preview how it would look like. I hope this makes sense.
I'm lost at how I could export this component from NextJS and import it into my dashboard. The dashboard is rendered in Ruby on Rails. It would be simple enough to just import the repo from git and access the file directly form node_modules, but I'm looking for a solution that doesn't require installing npm on our Rails project.
Paths I have thought about:
1 - Install npm on Rails and just import the source code from NextJS repo and access the file and render with react (Simple, but we're looking for a non-npm solution)
2 - Bundle the component with webpack and load it directly into rails (does this even work?) - I exported the js and all it did was freeze everything :P Still trying this path for now
3 - Using an iframe and just accessing the page (then I can't pass any callbacks into the iframe to change the color directly from the dashboard)
4 - I cannot separate this component from NextJS to use as a library in both repos. The component we are exporting is the "ENTIRE" NextJS app jsx and it wouldn't make sense to separate in a different repo
Does anyone have a suggestion on how I could achieve this?
I think you could use an iframe with the nextjs app url. Then if you want to change the color, simply add the color in query parameter of the iframe and handle it on nextjs app.
Simple example
Rails view (erb)
<iframe src="#{#nextjs_url}?color=#{#color}" />
NextJS
# do something to get the query param of the page and and set to prop of the component
const YourComponent = ({color}) => {
return <h1 style={{color}}>Lorem</h1>;
}
While trying Hoang's solution, I decided to dive deeper into how to communicate with an iframe and the solution actually feels quite good.
You can set up listeners on either side and post messages in between the projects.
So in my dashboard:
function handleEvent(e) {
const data = JSON.parse(e.data)
if (data.type === "card_click") {
//if type is what we want from this event, handle it
}
}
// Setup a listener with a handler
// This will run every time a message is posted from my app
window.addEventListener("message", handleEvent, false)
const postMessage = (color) => {
const event = JSON.stringify({
type: "color_update",
color,
})
// Find the iframe and post a message to it
// This will be picked up by the listener on the other side
document.getElementById("my-iframe-id").contentWindow.postMessage(event, "*")
}
And on my app:
function handleEvent(e) {
const data = JSON.parse(e.data)
if (data.type === "color_update") {
// Do whatever is necessary with the data
}
}
// Setup listener
// This will fire with every message posted from my dashboard
window.addEventListener("message", handleEvent, false)
const handleCardClick = (cardIndex) => {
const event = JSON.stringify({
type: "card_click",
cardIndex,
})
// post message to parent, that will be picked up by listener
// on the other side
window.parent.postMessage(event, "*")
}
It feels pretty straight forward to communicate with an iframe with this solution.

Correctly showing RTL languages in JIRA

Does anybody knows how to use JIRA with RTL languages?
It seems that their interface is not configurable to change the direction of text flow.
There is server side Jira plugin for this.
Right To Left Plugin for Jira
Thought I did not try it and of cause that means buying, installing etc.
There is also a chrome plugin
JiraRTL
(Disclaimer I am the creator of this plugin. And by the way, help wanted for maintaining it.)
I use Jira announcement banner to inject custom CSS or JS: How to add custom JS and CSS
Just add this code:
<script>
setInterval(function () {
let pegah_dirAutoSupportSelector =
".user-content-block:not([dir])";
const items = document.querySelectorAll(pegah_dirAutoSupportSelector);
items.forEach((x) => {
x.setAttribute("dir", "auto");
});
}, 1000);
</script>

Mapping URL in main menu to every page

I am using in my grails 2.3.4 project with spring security and spring securit ui.
I am having scaffolde my domain contact to the view. I have also a .gsp page which is not scarfolded.
My links from my main menue looks like that:
<li>Pricing</li>
<li>Contact</li>
Thats my URLMappings
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?(.${format})?"{
constraints {
// apply constraints here
}
}
"/private/$controller/$action?/$id?(.${format})?"{
constraints {
// apply constraints here
}
}
"/"(view:"/index")
"/pricing"(view:"/pricing")
"/private/dashboard"(view:"/private/dashboard")
"/contact/create"(view:"/contact/create")
"500"(view:'/error')
}
}
My problem is when I am using this two links from my mainpage / then everythings works fine. However using them from 5432:localhost/TestApp/pricing I am getting the link 5432:localhost/TestApp/pricing/contact/create
which goes is not available. If I am using <li>Contact</li>, I am going to 5432:localhost/contact/create, which is also not available. How to go to contact/create from every page?
I appreciate your reply!
The simplest and safest approach would be
<li><g:link uri="/contact/create">Contact</g:link></li>
Other attributes on the g:link tag will pass through to the generated a tag, with the exception of id - you need to use elementId instead, as id is treated as a parameter to the link generation (controller/action/id)
<li><g:link uri="/contact/create" class="nav" elementId="contactlink">Contact</g:link></li>
would become
<li>Contact</li>
(where /TestApp is the application context path - if you deploy the app at a different context path then then link will change to match).

How to remove a-tag's title param in tt_news using typoscript

The standard output of a tt_news list view hyperlink is like:
News Headline
How to remove the title tag from the standard output with typoscript ? So that you get:
News Headline
I' am looking for a typoscript something like:
plugin.tt_news.displayList.linkParams.ATagParams >
Info: The template (sub)marker which includes the hyperlink is called:
<!-- ###LINK_ITEM### -->
... some Headline ...
<!-- ###LINK_ITEM### -->
There is a hook for this.
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['getSingleViewLinkHook']
You will have to use it in an own extension.
Your hook consuming class will have to implement the following method
function processSingleViewLink(&$linkWrap, $url, &$params, &$pObj) {
// modify $linkWrap to remove title="" using regex
[...]
}
See here for reference how to consume hooks in TYPO3: http://typo3.org/documentation/article/how-to-use-existing-hooks-in-your-own-extension/
It's
plugin.tt_news.displayList.linkTitleField =
However title will be there, it will not be filled.
If you want to remove the empty title part as well you need to dive into the plugin to remove it.

Way to organize client-side templates into individual files?

I'm using Handlebars.js, and currently all my templates live inside script tags which live inside .html files housing dozens of other templates, also inside script tags.
<script type="text/template" id="template-1">
<div>{{variable}}</div>
</script>
<script type="text/template" id="template-2">
<div>{{variable}}</div>
</script>
<script type="text/template" id="template-3">
<div>{{variable}}</div>
</script>
...
Then I include this file on the server-side as a partial.
This has the following disadvantages:
A bunch of templates are crammed into HTML files.
Finding a given template is tedious.
I'm looking for a better way to organize my templates. I'd like each each template to live in its own file. For example:
/public/views/my_controller/my_action/some_template.html
/public/views/my_controller/my_action/some_other_template.html
/public/views/my_controller/my_other_action/another_template.html
/public/views/my_controller/my_other_action/yet_another_template.html
/public/views/shared/my_shared_template.html
Then at the top of my view, in the backend code, I can include these templates when the page loads, like this:
SomeTemplateLibrary.require(
"/public/views/my_controller/my_action/*",
"/public/views/shared/my_shared_template.html"
)
This would include all templates in /public/views/my_controller/my_action/ and also include /public/views/shared/my_shared_template.html.
My question: Are there any libraries out there that provide this or similar functionality? Or, does anyone have any alternative organizational suggestions?
RequireJS is really good library for AMD style dependency management. You can actually use the 'text' plugin of requireJS to load the template file in to your UI component. Once the template is attached to the DOM, you may use any MVVM, MVC library for bindings OR just use jQuery events for your logic.
I'm the author of BoilerplateJS. BoilerplateJS reference architecture uses requireJS for dependency management. It also provides a reference implementations to show how a self contained UI Components should be created. Self contained in the sense to handle its own view template, code behind, css, localization files, etc.
There is some more information available on the boilerplateJS homepage, under "UI components".
http://boilerplatejs.org/
I ended up using RequireJS, which pretty much let me do this. See http://aaronhardy.com/javascript/javascript-architecture-requirejs-dependency-management/.
I use a template loader that loads the template using ajax the first time it is needed, and caches it locally for future requests. I also use a debug variable to make sure the template is not cached when I am in development:
var template_loader = {
templates_cache : {},
load_template : function load_template (params, callback) {
var template;
if (this.templates_cache[params.url]){
callback(this.templates_cache[params.url]);
}
else{
if (debug){
params.url = params.url + '?t=' + new Date().getTime(), //add timestamp for dev (avoid caching)
console.log('avoid caching url in template loader...');
}
$.ajax({
url: params.url,
success: function(data) {
template = Handlebars.compile(data);
if (params.cache){
this.templates_cache[params.url] = template;
}
callback(template);
}
});
}
}
};
The template is loaded like this:
template_loader.load_template({url: '/templates/mytemplate.handlebars'}, function (template){
var template_data = {}; //get your data
$('#holder').html(template(template_data)); //render
})
there's this handy little jquery plugin I wrote for exactly this purpose.
https://github.com/cultofmetatron/handlebar-helper

Resources