このサイトはAtlassian製品に関わるエンジニア有志で運営するコミュニティサイトです。コミュニティサイトに登録された情報については免責事項となります。

Questions for Confluence license has expired.

Please purchase a new license to continue using Questions for Confluence.

チケットの背景色を変えたい

 
3
2
1

プロジェクト毎に特定の条件に該当しているかどうかを判断し、それに応じてチケットの背景色を変えようと思っており、まずはチケットの背景色を変更することができるかを調査しています。

現時点ではお知らせバナーに下記のようなjavascriptを埋め込んで一応動作はしたのですが、onloadで発火させているせいか、下図の赤枠で囲っている部分をクリックして新たなチケットを読み込んだり更新すると、背景色が通常通りにリセットされてしまいます。

<script>
window.onload = function(){
document.getElementsById("issue-content").style.backgroundColor = "red";
}
</script>


何かいい案は無いでしょうか?

    CommentAdd your comment...

    2 answers

    1.  
      3
      2
      1

      Kengo Ohsakiさん

      運用想定としては、権限に紐付けて、このプロジェクトはユーザー全員が見れます といったような警告を表示したいと思っているので、パーミッションスキームの名称に対しての条件付けができればありがたいです。
      (全員見れるパーミッションスキームの名称には、それとわかる文字列を書いておくという運用想定)

      1. Kengo Ohsaki

        蒼龍-san,

        パーミッションスキームを取得するために以下REST APIがありますが

        そのプロジェクトの管理者 または Jira管理者以外のユーザーでは403でデータ取得できません。

        https://docs.atlassian.com/software/jira/docs/api/REST/7.6.1/#api/2/project/{projectKeyOrId}/permissionscheme-getAssignedPermissionScheme

        残念ながら、権限上プロジェクトに設定しているパーミッションスキームの名称はそのプロジェクトの管理者 または Jira管理者ではないと参照できません。

        今気づいたのですが他のスキームも同じでしたね…


        そのため、プロジェクトカテゴリーとかがよいかと思いますが

        Jiraのプロジェクトカテゴリーはプロジェクトに1つしか設定できないので

        あとはプロジェクトの説明(description)に 「公開プロジェクト」など文字列を入れるておき

        それが入っているプロジェクトは赤くするなどしたらどうでしょうか?

        <script>
        (function() {
        	function hilightIssue(projectKey) {
        		if (!projectKey) {
        			return;
        		}
        		// 何度もREST APIで課題情報を取得しないようにチェック
        		if (AJS.$("#issue-content").attr('data-custom-hilight') === 'true') {
        			return;
        		}
        		AJS.$("#issue-content").attr('data-custom-hilight', 'true');
        
        		// REST APIで課題情報を取得
        		var url = AJS.contextPath() + "/rest/api/2/project/" + encodeURIComponent(projectKey);
        		AJS.$.ajax({
        			type: 'GET',
        			dataType: 'json',
        			contentType : 'application/json',
        			url: url,
        			async: false,
        			cache : false,
        			success: function(data) {
        				if (data.description && data.description.indexOf("公開プロジェクト") !== -1) {
        					AJS.$("#issue-content").css('backgroundColor', 'red');
        				}
        			},
        			error: function(XMLHttpRequest, textStatus, errorThrown) {
        				console.log(XMLHttpRequest.status);
        				console.log(XMLHttpRequest.statusText);
        				console.log(XMLHttpRequest.responseText);
        				return;
        			}
        		});
        	}
        	
        	JIRA.bind(JIRA.Events.NEW_CONTENT_ADDED, function (event, $context, reason) {
        		if (reason === JIRA.CONTENT_ADDED_REASON.pageLoad || reason === JIRA.CONTENT_ADDED_REASON.panelRefreshed) {
        			hilightIssue(getProjectKey());
        		}
        	});
        	
        	AJS.toInit(function() {
        		hilightIssue(getProjectKey());
        	});
        	
        	function getProjectKey() {
        		if (JIRA.API.Projects.getCurrentProjectKey()) {
        			return JIRA.API.Projects.getCurrentProjectKey();
        		}
        		return AJS.$("#project-name-val").text();
        	}
        })();
        </script>
        
        
        



      2. 蒼龍

        Kengo Ohsakiさん、 Shuzaburo Dobaさん

        説明欄から文字列を取得してそれを元にチケットのデザインを制御する方法を取ろうと思います。

        今後も色々付き合わせてしまうかもしれませんがよろしくお願いします

        ありがとうございました。

      3. Kengo Ohsaki

        蒼龍-san,

        HTMLに代入することもできますが、どのあたりに表示するかにもよるので何とも言えないですが

        見た目的にわかりやすくするためには  https://docs.atlassian.com/aui/7.9.1/docs/flag.html を使ったほうがいいかなと思います。

        <script>
        (function() {
        	var customHilightFlag;
        
        	function hilightIssue(projectKey) {
        		if (!projectKey) {
        			return;
        		}
        		// 何度もREST APIで課題情報を取得しないようにチェック
        		if (AJS.$("#issue-content").attr('data-custom-hilight') === 'true') {
        			return;
        		}
        		AJS.$("#issue-content").attr('data-custom-hilight', 'true');
        
        		if (customHilightFlag) {
        			customHilightFlag.close();
        			customHilightFlag = null;
        		}
        
        		// REST APIで課題情報を取得
        		var url = AJS.contextPath() + "/rest/api/2/project/" + encodeURIComponent(projectKey);
        		AJS.$.ajax({
        			type: 'GET',
        			dataType: 'json',
        			contentType : 'application/json',
        			url: url,
        			async: false,
        			cache : false,
        			success: function(data) {
        				if (data.description && data.description.indexOf("公開プロジェクト") !== -1) {
        					AJS.$("#issue-content").css('backgroundColor', 'red');
        					customHilightFlag = AJS.flag({
        					    type: 'warning',
        					    title: 'ご注意ください',
        					    body: '公開プロジェクト課題です',
        					});
        				}
        			},
        			error: function(XMLHttpRequest, textStatus, errorThrown) {
        				console.log(XMLHttpRequest.status);
        				console.log(XMLHttpRequest.statusText);
        				console.log(XMLHttpRequest.responseText);
        				return;
        			}
        		});
        	}
        	
        	JIRA.bind(JIRA.Events.NEW_CONTENT_ADDED, function (event, $context, reason) {
        		if (reason === JIRA.CONTENT_ADDED_REASON.pageLoad || reason === JIRA.CONTENT_ADDED_REASON.panelRefreshed) {
        			hilightIssue(getProjectKey());
        		}
        	});
        	
        	AJS.toInit(function() {
        		hilightIssue(getProjectKey());
        	});
        	
        	function getProjectKey() {
        		if (JIRA.API.Projects.getCurrentProjectKey()) {
        			return JIRA.API.Projects.getCurrentProjectKey();
        		}
        		return AJS.$("#project-name-val").text();
        	}
        })();
        </script>
        
        
        

        以下のようなメッセージが表示されるようになります。

      4. Kengo Ohsaki

        蒼龍-san.

        説明欄から文字列を取得してそれを元にチケットのデザインを制御する方法を取ろうと思います。

        入れ違いになりました。そうですね。色々な実現方法はあるかと思いますので御社で分かりやすい表示にしていただければと思います。


        最後に...Jiraではお知らせバナーのJavaScriptなどで細かくカスタマイズすることは技術的に可能ですが(他にもConfluenceではカスタムHTMLのJavaScriptなど、レイアウト・ユーザーマクロでのAPI操作)

        バージョンアップ都度にカスタマイズの動作確認なども必要になります。

        バージョンアップでの仕様変更によっては、別途改修することも必要になります。

        蒼龍様が継続しておられるのであれば安心ですが、運用引継ぎが必要になった場合、後任の担当者の技量によっては維持できない可能性もあります。

        技術的にできるからと言っても、こうした独自カスタマイズはサポートの観点からは少しおススメはできません。今後の運用を視野に入れてご検討いただければ幸いです。

        私も回答しておきながら矛盾していますが、リスクもあるということだけご理解頂ければ幸いです。

      CommentAdd your comment...
    2.  
      4
      3
      2

      参考QA

      Jiraの解決状況が設定されている課題や優先度が高い課題、特定のステータスなどで色付けをしたい


      製品標準機能ではできないので、上記QAで紹介しているアドオンをご評価頂くのが一番良いかとは思いますが...

      アドオンとしては Rainbow が近いですかね。


      どうしても要件が合致せずお知らせバナーのJavaScriptなどで細かくカスタマイズして実現しなくてはならないのであれば…

      課題更新イベントを取得すればいいので、例えば以下JavaScriptで常に赤くなるかと…

      <script>
      (function ($, AJS, _) {
      	JIRA.bind(JIRA.Events.NEW_CONTENT_ADDED, function (event, $context, reason) {
      		AJS.$("#issue-content").css('backgroundColor', 'red');
      	});
      	
      	AJS.toInit(function() {
      		AJS.$("#issue-content").css('backgroundColor', 'red');
      	});
      
      
      })(AJS.$, AJS, _);
      </script>


      上記だと無条件で常に赤色になるので、さらに発展させると以下のような感じでしょうか

      表示している課題の情報をREST APIで取得して、優先度が「最高」のものを赤く表示するイメージです。

      <script>
      (function ($, AJS, _) {
      	function hilightIssue(issueKey) {
      		// 何度もREST APIで課題情報を取得しないようにチェック
      		if (AJS.$("#issue-content").attr('data-custom-hilight') === 'true') {
      			return;
      		}
      		AJS.$("#issue-content").attr('data-custom-hilight', 'true');
      
      		// REST APIで課題情報を取得
      		var url = AJS.contextPath() + "/rest/api/2/issue/" + encodeURIComponent(issueKey);
      		AJS.$.ajax({
      			type: 'GET',
      			dataType: 'json',
      			contentType : 'application/json',
      			url: url,
      			async: false,
      			cache : false,
      			success: function(data) {
      				if (data && data.fields && data.fields.priority.name === '最高') {
      					AJS.$("#issue-content").css('backgroundColor', 'red');
      				}
      				return;
      			},
      			error: function(XMLHttpRequest, textStatus, errorThrown) {
      				console.log(XMLHttpRequest.status);
      				console.log(XMLHttpRequest.statusText);
      				console.log(XMLHttpRequest.responseText);
      				return;
      			}
      		});
      	}
      	
      	JIRA.bind(JIRA.Events.NEW_CONTENT_ADDED, function (event, $context, reason) {
      		if (reason === JIRA.CONTENT_ADDED_REASON.pageLoad || reason === JIRA.CONTENT_ADDED_REASON.panelRefreshed) {
      			hilightIssue(JIRA.Issue.getIssueKey());
      		}
      	});
      	
      	AJS.toInit(function() {
      		hilightIssue(JIRA.Issue.getIssueKey());
      	});
      })(AJS.$, AJS, _);
      </script>

      動作の保証はしませんが参考までに。

      1. Shuzaburo Doba

        なるほど REST API で取得すればいいのですね!!

        使用しているスキームから色を変えたいと思っていたので
        これで実現できそうです。

        ありがとうございます。

        <script>
        (function ($, AJS, _) {
            function hilightIssue(){
                var issueKey = JIRA.Issue.getIssueKey();
                var projectKey = JIRA.API.Projects.getCurrentProjectKey()
                var getWorkflowschemeUrl = AJS.contextPath() + '/rest/projectconfig/1/workflowscheme/' + encodeURIComponent(projectKey);
                var getIssueUrl = AJS.contextPath() + '/rest/api/2/issue/' + encodeURIComponent(issueKey);
        
                var issueTypeId;
                var workflowName;
        
        
                var xhr1 = new XMLHttpRequest();
                var xhr2 = new XMLHttpRequest();
                
                // 課題を取得
                xhr1.onreadystatechange = function(){
                    if(xhr1.readyState === 4){
                        if(xhr1.status === 200){
                            var data = JSON.parse(xhr1.responseText);
        
                            issueTypeId = data.fields.issuetype.id;
                            projectKey = data.fields.project.key;
                            
                            xhr2.send();
                        }else{
                            console.log('getIssueTypeId エラー : ' + xhr1.status);
                        }
                    }else{
                        console.log('getIssueTypeId 準備中... : ' + xhr1.readyState);
                    }
                };
        
                // ワークフロースキームを取得
                xhr2.onreadystatechange = function(){
                    if(xhr2.readyState === 4){
                        if(xhr2.status === 200){
                            var data = JSON.parse(xhr2.responseText);
                            var workFlowIdMappings = data.mappings;
                            
                            // 課題タイプをもとに使用しているワークフローを取得
                            loop: for(var i = 0; i < workFlowIdMappings.length; i++){
                                var issueTypes = workFlowIdMappings[i].issueTypes;
                                for(var j = 0; j < issueTypes.length; j++){
                                    if(issueTypes[j] == issueTypeId){
                                        workflowName = workFlowIdMappings[i].name;
                                        break loop;
                                    }   
                                }
                            }
                            changeBackground(workflowName);
        
                        }else{
                            console.log('getWorkflowName エラー : ' + xhr2.status);
                        }
                    }else{
                        console.log('getWorkflowName 準備中... : ' + xhr2.readyState);
                    }
                };
                
                // ワークフローごとに色を変える
                function changeBackground(workflowName){
                    switch(workflowName){
                        case 'copy of copy of Software Simplified Workflow for Project CONFGANTT':
                            AJS.$(".issue-header-content > .aui-page-header").css('backgroundColor', '#c47f7f');
                            break;
                        case 'copy of Software Simplified Workflow for Project CONFGANTT':
                            AJS.$(".issue-header-content > .aui-page-header").css('backgroundColor', '#7f89c4');
                    }
                }
                
                xhr1.open('GET', getIssueUrl);
                xhr1.send();
                xhr2.open('GET', getWorkflowschemeUrl);
                
            }
            
            
            JIRA.bind(JIRA.Events.NEW_CONTENT_ADDED, function (event, $context, reason) {
        		if (reason === JIRA.CONTENT_ADDED_REASON.pageLoad || reason === JIRA.CONTENT_ADDED_REASON.panelRefreshed) {
                    hilightIssue();
        		}
        	});
        	
        	AJS.toInit(function() {
                hilightIssue();
        	});
        })(AJS.$, AJS, _);
        </script>
      2. Kengo Ohsaki

        Shuzaburo Doba-san,

        素晴らしい。

        JavaScript は自由。

      3. 蒼龍

        JIRAのREST APIってどこかに解説やリファレンスってありますか?

        スキームが取れるならやりたい事ができそうなのですが、何をどう書けばいいのかわからず・・・

      4. Shuzaburo Doba

        https://docs.atlassian.com/software/jira/docs/api/REST/7.6.1/

        に記載されています。
        参考になりますと幸いです。

      5. Kengo Ohsaki

        蒼龍-san,

        利用方法以下とかも参考になるかと

        https://qiita.com/yutwatan/items/36291d3833eb963fa583

        https://www.ricksoft.jp/blog/archives/7021/

        公式開発ドキュメント:https://developer.atlassian.com/server/jira/platform/rest-apis/ (英語)


        まぁスキームでやらず、課題の情報のプロジェクトキーや課題タイプで

        色分けするほうがシンプルな気もしますけどね…


      6. 蒼龍

        Kengo Ohsakiさん、 Shuzaburo Dobaさん

        ありがとうございます。

        まぁスキームでやらず、課題の情報のプロジェクトキーや課題タイプで
        色分けするほうがシンプルな気もしますけどね…

        そうできれば一番いいのですが、プロジェクトレベルで何かしらの分類をして、分類ごとに色分けをするというのが目的なので、プロジェクトキーや課題タイプだと想定している仕様とは違うものになってしまうのです・・・

        後、お二人が息をするように使いこなされていてただただ凄いですw

        引数で使われている$,AJS,_,どうも既に定義されてる(?)JIRAとかどう使えばいいのかも分からず・・・ドが付くほどの素人で申し訳ないのですが、このあたりの使い方もご教授いただけないでしょうか?

      7. Kengo Ohsaki

        蒼龍-san,

        プロジェクトレベルで何かしらの分類をして、分類ごとに色分けをするというのが目的なので、プロジェクトキーや課題タイプだと想定している仕様とは違うものになってしまうのです・・・

        なるほど。プロジェクトレベルであれば、プロジェクトカテゴリーはダメですかね…

        REST APIの課題情報に含まれているので以下のような形でも実現できます。

        <script>
        (function() {
        	function hilightIssue(issueKey) {
        		// 何度もREST APIで課題情報を取得しないようにチェック
        		if (AJS.$("#issue-content").attr('data-custom-hilight') === 'true') {
        			return;
        		}
        		AJS.$("#issue-content").attr('data-custom-hilight', 'true');
        
        		// REST APIで課題情報を取得
        		var url = AJS.contextPath() + "/rest/api/2/issue/" + encodeURIComponent(issueKey);
        		AJS.$.ajax({
        			type: 'GET',
        			dataType: 'json',
        			contentType : 'application/json',
        			url: url,
        			async: false,
        			cache : false,
        			success: function(data) {
        				if (data.fields.project.projectCategory.name === '<プロジェクトカテゴリ名>') {
        					AJS.$("#issue-content").css('backgroundColor', 'red');
        				}
        			},
        			error: function(XMLHttpRequest, textStatus, errorThrown) {
        				console.log(XMLHttpRequest.status);
        				console.log(XMLHttpRequest.statusText);
        				console.log(XMLHttpRequest.responseText);
        				return;
        			}
        		});
        	}
        	
        	JIRA.bind(JIRA.Events.NEW_CONTENT_ADDED, function (event, $context, reason) {
        		if (reason === JIRA.CONTENT_ADDED_REASON.pageLoad || reason === JIRA.CONTENT_ADDED_REASON.panelRefreshed) {
        			hilightIssue(JIRA.Issue.getIssueKey());
        		}
        	});
        	
        	AJS.toInit(function() {
        		hilightIssue(JIRA.Issue.getIssueKey());
        	});
        })();
        </script>


        引数で使われている$,AJS,_,どうも既に定義されてる(?)JIRAとかどう使えばいいのかも分からず・・・ドが付くほどの素人で申し訳ないのですが、このあたりの使い方もご教授いただけないでしょうか?

        引数の $,AJS,_, はすみません、変数にアクセスしやすくするだけのもので必須ではありませんので無視してください。

        (function() はJavaScriptの即時関数を使用したほうが、まぁ何かと良いのでよく使用されます。

        http://unitopi.com/js-function/


      8. Shuzaburo Doba

        プロジェクトカテゴリだと、

        AJS.Meta.get('issue-project-type')

        からも取得できそうでした!

        (function() {
        	function hilightIssue() {
        		var projectCategory = AJS.Meta.get('issue-project-type');
        		switch(projectCategory){
        			case 'software':
        				AJS.$('.issue-header-content > .aui-page-header').css('backgroundColor', '#ffd000');
        				break;
        			case 'service_desk':
        				AJS.$('.issue-header-content > .aui-page-header').css('backgroundColor', '#35cc4e');
        				break;
        			case 'business':
        				AJS.$('.issue-header-content > .aui-page-header').css('backgroundColor', '#3556e8');
        				break;
        		}
        	}
        	
        	JIRA.bind(JIRA.Events.NEW_CONTENT_ADDED, function (event, $context, reason) {
        		if (reason === JIRA.CONTENT_ADDED_REASON.pageLoad || reason === JIRA.CONTENT_ADDED_REASON.panelRefreshed) {
        			hilightIssue();
        		}
        	});
        	
        	AJS.toInit(function() {
        		hilightIssue();
        	});
        })();
      9. Kengo Ohsaki

        Shuzaburo Doba-san

        それ プロジェクトタイプ かな。


      10. Shuzaburo Doba

        ...申し訳ありません。
        大変失礼しました。

      11. Kengo Ohsaki

        Shuzaburo Doba-san,

        いえいえ。何も悪いことでないので謝らないで。

      CommentAdd your comment...