Trac
Trac是一套问题追踪系统(英语:Issue tracking system)。
简介
优点
- 简单,专住在事情的记录上,而不是限制行为上。
缺点
- 目前还是不支援Python 3。
安装
除了基本安装外,还会安装这些套件:
- 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。
以前会安装的:
- DefaultCcPlugin – Trac Hacks - Plugins Macros etc.
- 针对不同的Component设定Cc列表,对于企业内还蛮有用的。像是专案可以开
Proj.
开头的Component,而组织可以开Org.
开头的Component,这些类型可以设定对应的Cc列表。
- 针对不同的Component设定Cc列表,对于企业内还蛮有用的。像是专案可以开
看过但还没用过的:
- AccountManagerPlugin – Trac Hacks - Plugins Macros etc.
- 说明提到可以吃HTML Form Login,而不局限在HTTP authentication。
设定
在templates/site.html
里做了一些事情进行客制化。
CSS
- 全部使用sans-serif字型。
- 修正button因为CSS效果而有时会按不到的问题。
- 针对今天到期与过期的票用不同的标示标出。
- 将已经关掉的票变淡。
- 让编辑区域使用等宽字型。
- 让可用范围变宽。
<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; } 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; } --> </style>
JavaScript
- 用JavaScript针对今天到期以及过期的票增加CSS。
- 将新票里的Due Date改为零点零分零秒。
- 将票里的attachments与modify内容展开。
- 将日历选择器中,每周的第一天设为星期天。另外允许选择其他月份的日期。
<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 if ('/newticket' === document.location.pathname) { var el = jQuery('#field-due_date'); el.val(el.val().replace(/T.+Z/, 'T00:00:00Z')); } // Closed tickets handling jQuery('tr:has(a.closed)').addClass('ticket_closed'); // Datepicker jQuery.datepicker.setDefaults({firstDay: 0, selectOtherMonths: true, showOtherMonths: true}); })(); // Run after content loaded. jQuery(function() { // Layout jQuery('#attachments').removeClass('collapsed'); jQuery('#modify').parent().removeClass('collapsed'); }); //--> </script>