「Trac」:修訂間差異
第263行: | 第263行: | ||
} while (false); | } while (false); | ||
} | } | ||
// Accept & start buttons | |||
$('#action_accept').each(function(){ | |||
var v = $(this).val(); | |||
var b = document.createElement('button'); | |||
b.addEventListener('click', function(e){ | |||
var v = $(this).val(); | |||
$('#action_accept').click(); | |||
$('#propertyform input[name="submit"]').click(); | |||
e.preventDefault(); | |||
}); | |||
b.innerHTML = v; | |||
b.setAttribute('value', v); | |||
$(this).closest('div').append(b); | |||
}); | |||
$('#action_start').each(function(){ | |||
var v = $(this).val(); | |||
var b = document.createElement('button'); | |||
b.addEventListener('click', function(e){ | |||
var v = $(this).val(); | |||
$('#action_start').click(); | |||
$('#propertyform input[name="submit"]').click(); | |||
e.preventDefault(); | |||
}); | |||
b.innerHTML = v; | |||
b.setAttribute('value', v); | |||
$(this).closest('div').append(b); | |||
}); | |||
// Resolve with Buttons | // Resolve with Buttons | ||
$('#action_resolve_resolve_resolution option').each(function(){ | $('#action_resolve_resolve_resolution option').each(function(){ | ||
var v = $(this).val(); | var v = $(this).val(); | ||
第278行: | 第309行: | ||
e.preventDefault(); | e.preventDefault(); | ||
}); | }); | ||
b.innerHTML = | b.innerHTML = v; | ||
b.setAttribute('value', v); | b.setAttribute('value', v); | ||
於 2018年7月5日 (四) 10:00 的修訂
Trac是一套問題追蹤系統(英語:Issue tracking system)。
簡介
優點
- 簡單,專注在事情的記錄上,而不是限制行為上。
缺點
- 目前還是不支援Python 3。
安裝
我是將Python裝在www-data
這個使用者的pyenv裡面(權限會是www-data:www-data
)。在裝完Python後,用pip
安裝以下套件:
$ pip install Trac
$ pip install Pygments
$ pip install mysql-python
使用MySQL作為後端資料庫時,建議用utf8mb4作為基礎,這樣資料庫可以存所有範圍的Unicode字元[1],另外建立獨立的使用者供Trac使用:
CREATE DATABASE trac DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
GRANT ALL ON trac.* TO `trac`@`localhost` IDENTIFIED BY 'password_here';
這樣在安裝Trac時的連線設定會是mysql://trac:password_here@localhost/trac
(需要自己修改對應欄位)。
在安裝套件時,軟體本體常常會放在Subversion的伺服器內,在透過pip
或是easy_install
時會呼叫Subversion,所以會需要安裝對應的軟體:
# apt install subversion
另外要建立目錄,並且讓Trac可以寫入:
# mkdir trac/files
# chown www-data:www-data trac/files
然後是Trac的FastCGI檔案,放在Trac的project目錄下,並且用chmod 755 trac.fcgi
改成可執行:
#!/usr/bin/env python
import os
from trac.web.main import dispatch_request
import trac.web._fcgi
num = 2
sockaddr = '/var/run/trac/trac.sock'
os.environ['TRAC_ENV'] = os.path.dirname(__file__)
fcgiserv = trac.web._fcgi.WSGIServer(dispatch_request, bindAddress = sockaddr, umask = 7)
num -= 1
while num > 0:
num -= 1
if 0 == os.fork():
break
fcgiserv.run()
另外Systemd的設定檔讓Trac在開機時以FastCGI模式跑起來,這個檔案放在/lib/systemd/system/rsyslog.service
並連結到/etc/systemd/system/multi-user.target.wants/trac.service
下(要記得把裡面的/srv/trac.example.com/trac/
改成自己的目錄:
[Unit]
Description=trac fcgi daemon
[Service]
Type=simple
ExecStartPre=/bin/sh -c "/bin/mkdir -p /var/run/trac; /bin/chown www-data:www-data /var/run/trac; /bin/chmod 0755 /var/run/trac"
ExecStart=/bin/su - www-data -c "exec /srv/trac.example.com/trac/trac.fcgi"
[Install]
WantedBy=multi-user.target
目前有安裝的
除了基本安裝外,還會安裝這些套件:
- DuplicateTicketSearchPlugin – Trac Hacks - Plugins Macros etc.
- 在開新票時可以拉出有哪些是可能重複的票(尤其是已經關掉的票)。
- GraphvizPlugin – Trac Hacks - Plugins Macros etc.
- Graphviz可以拿來畫各類圖,我自己最常用的是Dot圖。
- SubticketsPlugin – Trac Hacks - Plugins Macros etc.
- 子母票的延伸套件,基本上是必備項目。
- TracCronPlugin – Trac Hacks - Plugins Macros etc.
- 定時跑任務,但其實沒很好用... 目前主要是拿來每天寄信通知有哪些票過期。
- TracDragDropPlugin – Trac Hacks - Plugins Macros etc.
- 拖拉就可以上傳附件的套件。
- TracWysiwygPlugin – Trac Hacks - Plugins Macros etc.
- 可以針對Textarea區塊使用WYSIWYG界面,對於非技術類的使用者來說會方便不少(因為不需要學Trac的Wiki語法)。另外有不少文件可以直接剪下貼上(雖然還是會掉不少效果,但比起完全不能剪下貼上來說已經方便不少)。
- XmlRpcPlugin – Trac Hacks - Plugins Macros etc.
- 讓使用者可以透過API操作Trac。
目前Trac 1.2版的安裝方式是:
#!/bin/bash
pip install svn+https://trac-hacks.org/svn/duplicateticketsearchplugin/trunk/
pip install svn+https://trac-hacks.org/svn/graphvizplugin/branches/1.2/
pip install git+https://github.com/trac-hacks/trac-subtickets-plugin.git
pip install TracCronPlugin
pip install svn+https://trac-hacks.org/svn/tracwysiwygplugin/0.12/
pip install TracXMLRPC
以前有安裝的
以前會安裝,但現在因為自己用而沒有裝上(沒有需求或是不想裝):
- AccountManagerPlugin – Trac Hacks - Plugins Macros etc.
- 說明提到可以吃HTML Form Login,而不侷限在HTTP authentication。
- AutocompleteUsersPlugin – Trac Hacks - Plugins Macros etc.
- 讓使用者帳號名稱可以autocomplete,在Cc欄位與Owner欄位會很好用。
- DefaultCcPlugin – Trac Hacks - Plugins Macros etc.
- 針對不同的Component自動加上Cc列表。
- 對於企業內還蠻有用的。像是專案可以開
Proj.
開頭的Component,而組織可以開Org.
開頭的Component,這些類型可以設定對應的Cc列表。 - 因為新版在更改Component時不會增加Cc列表,但這對於企業其實還蠻好用的,所以我自己包了一個版本在gslin/defaultccplugin這邊。
- LDAPAcctMngrPlugin – Trac Hacks - Plugins Macros etc.
- 可以使用LDAP管理帳號,是AccountManagerPlugin的延伸套件。
- SlackIntegration – Trac Hacks - Plugins Macros etc.
- 可以把變更丟到Slack上。
- gslin/trac-addtocc-plugin: Add participator to cc list automatically.
- 自動把參與者加到Cc列表內,這樣才會收到後續的更新。
- gslin/trac-secret-checkbox-ticket: Add ticket security policy for Trac.
- 將票設定為祕密,只有Reporter(開票人)、Owner(目前有票的人)、Cc列表內的人可以讀。
- 這對於企業內有些需求很好用(像是還在進行中的計畫,或是一些不會對全公司公開的數據)。
- TracTicketReferencePlugin – Trac Hacks - Plugins Macros etc.
- 可以設定相關連的票,不過我很少用到這個功能(更多是子母票)。
設定
權限
Trac預設的權限設定過於嚴格,只給內部使用的情境下,建議對authenticated
群組加上:
TICKET_EDIT_CC
TICKET_EDIT_DESCRIPTION
trac.ini
我自己的Report不想分頁(預設是一頁100筆),所以設為:
[report]
items_per_page = 0
讓系統吃code.jquery.com
所提供的jQuery以及jQuery UI[2],稍微降低伺服器的負載,另外也有機會與外部網站共用cache。目前的Trac 1.2.2版本可以這樣設:
[trac]
jquery_location = https://code.jquery.com/jquery-1.12.4.min.js
jquery_ui_location = https://code.jquery.com/ui/1.12.1/jquery-ui.min.js
jquery_ui_theme_location = https://code.jquery.com/ui/1.12.1/themes/start/jquery-ui.css
另外因為我們不太用Trac內建的Wiki,但又關不掉,所以只能針對沒找到的頁面就不要產生連結了:
[wiki]
ignore_missing_pages = enabled
site.html
在templates/site.html
裡做了一些事情進行客製化。
對於外部引用,不要 洩漏Referrer
:
<head>
<meta name="referrer" content="no-referrer" />
...
</head>
CSS
- 全部使用sans-serif字型。
- 修正button因為CSS效果而有時會按不到的問題。
- 針對code block內一行過長時自動換行。
- 針對今天到期與過期的票用不同的標示標出(配合下方的JavaScript)。
- 將已經關掉的票變淡(配合下方的JavaScript)。
- 讓編輯區域使用等寬字型。
- 讓可用範圍變寬。
- 讓圖片不要超過螢幕寬度。
<style type="text/css">
<!--
body, th, tr {
font-family: sans-serif;
}
input[type=button]:active, input[type=submit]:active,
input[type=reset]:active {
position: relative;
top: 0;
left: 0;
}
pre {
white-space: pre-wrap;
}
table.tickets tr.duedate_overdue {
font-weight: bold;
}
table.tickets tr.duedate_today {
border: 2px solid;
}
table.subtickets tr.ticket_closed, .closed.ticket {
opacity: 0.5;
}
textarea {
font-family: monospace;
}
#content.ticket {
width: 78em;
}
#main img {
max-width: 100%;
}
-->
</style>
JavaScript
- 用JavaScript針對今天到期以及過期的票增加CSS。
- 將新票裡的Due Date改為零點零分零秒。
- 增加button,讓關票可以直接點擊。
- 將票裡的attachments與modify內容展開。
- 將開票人的資訊放到Action欄位裡,比較好確認這張票的情況。
- 將日曆選擇器中,關閉動畫效果[3],另外將每週的第一天設為星期天[3],並且允許選擇其他月份的日期[3]。
在head
的地方先加入strftime
套件,後面會用到:
<script src="https://cdn.jsdelivr.net/npm/strftime@0.10.0/strftime.min.js"></script>
這段程式碼則會放在</body>
結尾前:
<script>
<!--
// Run immediately.
(function($) {
// Due date css handling
var d = new Date();
var today = (new Date(d.getTime() - d.getTimezoneOffset() * 60000)).toISOString().slice(0, 10);
document.querySelectorAll('table.tickets td.due_date').forEach(function(el) {
var due = el.innerText.trim();
if (due < today) {
el.parentElement.classList.add('duedate_overdue');
} else if (due === today) {
el.parentElement.classList.add('duedate_today');
}
});
// Due date (newticket) set to 00:00:00 (in UTC)
if ($('form[action$="/newticket#ticket"]').length > 0) {
do {
let el = $('#field-due_date');
let t = el.val();
if ('Z' === t.slice(-1)) {
console.log(t);
t = new Date(Date.parse(t) + 86400000);
t = strftime('%Y-%m-%dT00:00:00Z', t);
el.val(t);
break;
}
let a = t.match(/\+(\d\d:\d\d)$/);
if (null !== a) {
let tz = a[1];
let new_str = 'T' + tz + ':00+' + tz;
t = new Date(Date.parse(t) + 86400000);
t = strftime('%Y-%m-%d' + new_str, t);
el.val(t);
break;
}
} while (false);
}
// Accept & start buttons
$('#action_accept').each(function(){
var v = $(this).val();
var b = document.createElement('button');
b.addEventListener('click', function(e){
var v = $(this).val();
$('#action_accept').click();
$('#propertyform input[name="submit"]').click();
e.preventDefault();
});
b.innerHTML = v;
b.setAttribute('value', v);
$(this).closest('div').append(b);
});
$('#action_start').each(function(){
var v = $(this).val();
var b = document.createElement('button');
b.addEventListener('click', function(e){
var v = $(this).val();
$('#action_start').click();
$('#propertyform input[name="submit"]').click();
e.preventDefault();
});
b.innerHTML = v;
b.setAttribute('value', v);
$(this).closest('div').append(b);
});
// Resolve with Buttons
$('#action_resolve_resolve_resolution option').each(function(){
var v = $(this).val();
var b = document.createElement('button');
b.addEventListener('click', function(e){
var v = $(this).val();
$('#action_resolve').click();
$('#action_resolve_resolve_resolution').attr('disabled', false);
$('#action_resolve_resolve_resolution').find('option[value="' + v + '"]').attr('selected', 'selected');
$('#propertyform input[name="submit"]').click();
e.preventDefault();
});
b.innerHTML = v;
b.setAttribute('value', v);
$(this).closest('div').append(b);
});
// Closed tickets handling
$('tr:has(a.closed)').addClass('ticket_closed');
// Copy reporter information to action section
if ($('#action_resolve_resolve_resolution').length > 0) {
var reporter = $('#h_reporter').parent().find('.trac-author, .trac-author-user')[0].outerHTML;
$('#action_resolve_resolve_resolution').each(function(){
$(this).parent().append('<span class="hint">(This ticket is created by ' + reporter + ')</span>');
});
}
})(jQuery);
// Run after content loaded.
jQuery(function() {
// Layout
jQuery('#attachments').removeClass('collapsed');
jQuery('#modify').parent().removeClass('collapsed');
// Datepicker
if ($.datepicker) {
$.datepicker.setDefaults({
firstDay: 0,
selectOtherMonths: true,
showAnim: '',
showOtherMonths: true
});
}
});
//-->
</script>
其他
刪除使用者時可能會需要手動到以下表格清除資料(清完後需要重跑Trac,因為Trac會讀出來cache一份),避免autocomplete之類的套件仍然顯示:
- auth_cookie
- session
- session_attribute
著名使用單位
- Django
- FFmpeg
- nginx
- Tor
- WebKit
- WordPress
- jQuery
相關連結
參考資料
- ↑ MySqlDb – The Trac Project. [2018-03-01].
- ↑ TracIni – The Trac Project. [2018-02-28].
- ↑ 3.0 3.1 3.2 Datepicker Widget | jQuery UI API Documentation. [2018-02-28].