Follow the discussion and send feedback in this forum post.
This little (just kidding) template is really easy to customize. With the same Template I was able to make a Bug-tracker for the codemonkeys at my office, an Issue-tracker for the project managers, an IT Support request system and a Library database for the bookies. As I said, its easy to customize. The TicketForm template creates a form for new additions to the system and a table of existing systems (Note that you can also use the Datatable template for this. Just a bit of modification). The Ticket template creates a page that holds the Ticket properties and allows you to change them dynamically using JQuery and AJAX access to the API. Of course, there are comments (or 'notes' if you prefer the Mantis terminology) as with any wiki page.
The system as a whole just creates new pages for Tickets and stores the data in page properties. The information is displayed on the ticket page with the Ticket template. This way Lucene can pick up on them. The table on the Ticket form page is pretty much the Datatable template, just integrated. Though you don't need to have to datatable template, it would make the code for the TicketForm much shorter!
This uses my favorite table sorting and filtering system ever. That uses JQuery, my favorite javascript library ever. So this project is my baby.
NOTE: This was written for 9.02, but I'm sure it can be rewritten to work for other versions.
I started this template when I had just learned about using AJAX and Dekiscript in a template. I had just picked up interest in forms and I wanted to play with creating a form that submits through AJAX. I began work at home because I didn't want to waste my employer's time and money on something that may not pan out.
Well, it did pan out. It panned WAY out. Since posting here, it has grown ten-fold and is now a large application that we here at Multiphase use for many, many purposes. I left it here and continue to support it because I felt that the exponential growth of the application came from the bug-fixes and suggestions from users here. I could not have rigorously tested the script nor could I have thought of all of the features to add to it without your help. So, thank you!
Don't forget to send feedback! If you liked it, tell me! If you would like to see changes, tell me! Bugs? New features? Ideas? TELL ME!
Here are the templates necessary:
| Version | Change |
|---|---|
| v2.8 | - Solved the bug with special chars on Title - Added a parameter to TicketForm wich allows to pass subpage content ( insted of adding Ticket(), add for instance MyPersonalizedTicket() ) |
| v2.7 | Added a suggestion field type. (Similar to Auto-complete) |
| v2.6 | Added a resizable option to textareas. Thanks graynotgrey! |
| v2.5.2 | Fixed an option-escaping bug. |
| v2.5.1 | Removed download csv option. Instead, it outputs the csv code. |
| v2.5 | Added even more customization (see here). Added more filtering options. |
| v2.0 | Added extreme customization options, added export to csv, fixed a bug where pages don't redirect properly if there are more than 1 space in the title. |
| v1.2 | Added Sorting images and pagination images (in the boring version of the pagination) |
| v1.1.4 | Fixed a bug where the whole url wasn't being encoded, just the page name. |
| v1.1.3 | Cleaned up more code - Added JSON.Emit calls (I was doing it by hand. OOPS) |
| v1.1.2 | Form now redirects to the newly created page properly. Cleaned up the code a bit. |
| v1.1.1 | Fixed Show-only selects (They weren't filtering by column only), added stacking to show-only selects and added Clear filter button. |
| v1.1 | Added dynamic options. Tickets now read the options from the parent page's options (i.e. - the TicketForm's options.) |
| v1.0.3 | No longer have to use the modified Datatables.js file. Added Show-Only selects that filter by status, type, assignee and urgency. |
| v1.0.2 | Fixed bug in IE which prevented Datatables from initiating. Added a new style of Pagination which shows page numbers and next/previous buttons. |
| v1.0.1 | Removed <SELECT> from table because sorting and searching did not work. |
| v1.0 | Posted to this Wiki |
/**
Author: Blake Harms
Version 2.9
See: http://developer.mindtouch.com/App_Catalog/Integrated_Bug_and_Issue_Tracker
on 2.9 added performance tunning posted by Sego on this blog post: http://forums.developer.mindtouch.com/showthread.php?5882-Integrated-Bug-tracker-Support-Ticket-Library-with-JQuery&p=45759#post45759
*/
// ~~ Parameters ~~
var parameters = $0 ?? $options ?? [
{'title': {label:'Title',type:'text'}},
{'type': {data:['Bug','Support'],label:'Type',show:'both'}},
{'urgency': {data:['Low','Medium','High'],label:'Urgency',show:'both'}},
{'assign': {data:[u.name foreach var u in site.users where !u.anonymous],label:'Assign',show:'both', type:'suggest'}},
{'status': {data:{'#FBB':'Open','#FBF':'Assigned','#CCF':'Fix Issued','#DDD':'Closed','#AFA':'Fixed'},label:'Status'}},
{'summary': {label:'Summary',type:'textarea', show:'ticket'}},
{'time': {data:date.now,type:'hidden',show:'table'}}
];
// -- Added by carles.coll 2010/12/27
var new_page_content = $1 ?? $new_page_content ?? '<pre class=\\'script\\'> Ticket() </pre>';
var params = [];
foreach(var param in parameters){
let params ..= Map.keyValues(param);
}
if(! list.contains(list.collect(params,'key'),'title')){
<div style="font-weight:bold;color:red;">"Warning: A title field must be assigned."</div>
}
dekiapi();
jquery.ui("smoothness");
var options = "{'params':'" .. String.serialize(params) .. "'}";
var updateOptions = false;
if(page.properties.options.text != options){
let updateOptions=true;
let options = String.replace(String.replace(options,'"','\\"'),"'","\\'");
}
<html><head>
<script type="text/javascript" src="http://www.datatables.net/media/javascript/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="http://jqplugins.appspot.com/js/jquery.table2csv.js"></script>
<script type="text/javascript" src="http://developer.mindtouch.com/@api/deki/files/4634/=jquery.autocomplete.pack.js"></script>
<link rel="stylesheet" type="text/css" href="http://developer.mindtouch.com/@api/deki/files/4635/=jquery.autocomplete.css" />
<script type="text/javascript">"
var oTable;
Deki.$(document).ready(function(){
oTable = Deki.$('#"..@tickets.."').dataTable();
Deki.$('table.display tfoot select').change(filter);
Deki.$('table.display tfoot input').keyup(filter);
Deki.$('.datepicker').datepicker();
Deki.$('.resizable').resizable();
});
"</script>
if(updateOptions){
<script type="text/javascript">"
// Set page property 'options' with the options submitted to this template.
var prop = 'urn:custom.mindtouch.com#' + 'options'; // url that retrieves the ticket options
Deki.Api.ReadPageProperty(null, prop, function(result) {
if(result.etag) { // page property exists, write over it.
Deki.Api.UpdatePageProperty(result.href, '"..options.."', result.etag, function() {
}, function(result) {
// alert('An error occurred trying to update the store (status: ' + result.status + ' - ' + result.text + ')');
});
} else { // page property doesn't exist, create one.
Deki.Api.CreatePageProperty(null, prop, '"..options.."', null,null);
}
}, function(result) {
//alert('An error occurred trying to read the store (status: ' + result.status + ' - ' + result.text + ')');
});
"</script>
}
<script type="text/javascript">"
var filter= function() {
Deki.$('table.display tfoot select, table.display tfoot input').each(function() {
oTable.fnFilter(Deki.$(this).val(),$('table.display tfoot th').index(Deki.$(this).parent()));
});
}
var saveTicket= function(page, properties){
// Hide the ability to change stuff.
Deki.$('#saveButton').attr('value','Saving...').attr('disabled','disabled');
Deki.$('#" .. @form .. " tbody').find('input,select,textarea').each(function(){
$(this).attr('disabled','disabled');
});
saveProperty(page,properties); // recursive...
}
var saveProperty= function(page, properties){ // NOTE: This function is recursive. It will call itself for all of properties.
var propertyname;
var propertytext;
var first = false;
var theRest= new Array(); // the rest of the array.
for(var key in properties){
if(! first){
first = true;
propertyname = key;
propertytext = properties[key];
}
else {
theRest[key] = properties[key];
theRest.length++;
}
}
var pageapi = '/@api/deki/pages/=' + Deki.url.encode(Deki.url.encode(page));
// no need to check for update as we just created this page.
Deki.Api.CreatePageProperty(pageapi, 'urn:custom.mindtouch.com#' + propertyname, propertytext, function() {
if(theRest.length > 0){
saveProperty(page,theRest); // recurse
}
else{
location.href = '/' + page;
}
}, function(result) {
// just ignore it...
alert('An error occurred trying to create the store (status: ' + result.status + ' - ' + result.text + ')');
});
}
"</script>
<style type="text/css">"
/* Ticket Table CSS */
.dataTables_wrapper { position: relative; min-height: 302px; _height: 302px; clear: both; }
.dataTables_processing { position: absolute; top: 0px; left: 50%; width: 250px; margin-left: -125px; border: 1px solid #ddd; text-align: center; color: #999; font-size: 11px; padding: 2px 0; }
.dataTables_length { width: 40%; float: left; }
.dataTables_filter { width: 50%; float: right; text-align: right; }
.dataTables_info { width: 60%; float: left; }
.dataTables_paginate { float: right; text-align: right;padding:10px; }
/* DataTables display */
table.display { margin: 0 auto; clear: both;width:100%; }
table.display thead th { padding: 3px 10px; border-bottom: 1px solid black; font-weight: bold; cursor: pointer; _cursor: hand;text-align:center; }
table.display tfoot th { padding: 3px 10px; border-top: 1px solid black; font-weight: bold;text-align:center; }
table.display tr.heading2 td { border-bottom: 1px solid #aaa; }
table.display td { padding: 3px 10px; text-align:center }
table.display td.center { text-align: center; }
/* sorting */
.sorting_asc { background: url('http://www.datatables.net/media/images/sort_asc.jpg') no-repeat center right; }
.sorting_desc { background: url('http://www.datatables.net/media/images/sort_desc.jpg') no-repeat center right; }
.sorting { background: url('http://www.datatables.net/media/images/sort_both.jpg') no-repeat center right; }
/* paginate */
.paginate_disabled_previous, .paginate_enabled_previous, .paginate_disabled_next, .paginate_enabled_next { height: 19px; width: 19px; margin-left: 3px; float: left; }
.paginate_disabled_previous { background-image: url('http://www.datatables.net/media/images/back_disabled.jpg'); }
.paginate_enabled_previous { background-image: url('http://www.datatables.net/media/images/back_enabled.jpg'); }
.paginate_disabled_next { background-image: url('http://www.datatables.net/media/images/forward_disabled.jpg'); }
.paginate_enabled_next { background-image: url('http://www.datatables.net/media/images/forward_enabled.jpg'); }
/* Pagination nested */
.paginate_button, .paginate_active { border:1px solid black; padding:0px 3px; text-align:center; -moz-border-radius:3px;margin:3px;font-size:12px; } .paginate_button { background-color: #F0F0F0; cursor:pointer; _cursor:hand; }
.paginate_active { font-weight:bold;background-color: #DDD; }
table.display tr.odd { background-color: #F0F0F0; }
table.display tr.even { background-color: white; }
"</style>
if(list.contains(list.collect(params,'key'),'status')){
<style type="text/css">"
/* Ticket Table CSS */
.new { background-color: #FFFFA7 !important; }
"</style>
var status = list.collect(params,'value')[list.indexof(list.collect(params,'key'),'status')]; // This is absolutely wicked. Is there a better way?
<style type='text/css'>
foreach(var s in Map.keyvalues(status.data)){
"."..String.replace(String.ToLower(s.value),' ','').." { background-color:"..s.key.." !important; }";
}
</style>
}
</head></html>
<form id=(@submit)>
<table class="submitform" cellspacing="0" cellpadding="5" border="1" id=(@form)>
<tbody>
foreach(var param in params){
if(param.value.type=='hidden') continue; // skip the hidden values.
<tr>
<td> param.value.label ?? String.ToCamelCase(param.key)</td>
// check for type variable. if non-existant, determine based on data.
var type= param.value.type;
if(! type){
if(param.value.data is list || param.value is map) let type = 'select';
if(!param.value.data || param.value.data is str) let type = 'text';
}
<td>
switch(type){
case 'suggest':
if(param.value.data is list){
<input type="text" name=(String.toLower(String.replace(param.key,' ','_'))) style=(param.value.style.form) value=(param.value.data) ctor=(
"$this.autocomplete("..JSON.emit(param.value.data)..");") />
}
break;
case 'text':
<input type="text" name=(String.toLower(String.replace(param.key,' ','_'))) style=(param.value.style.form) value=(param.value.data) />
break;
case 'textarea':
var resizable = (typeof param.value.resizable == typeof null || param.value.resizable) ? 'resizable' : '';
<textarea class=(resizable) name=(String.toLower(String.replace(param.key,' ','_'))) style=(param.value.style.form)>param.value.data</textarea>
break;
case 'datepicker':
<input type="text" class="datepicker" name=(String.toLower(String.replace(param.key,' ','_'))) style=(param.value.style.form) value=(param.value.data) />
break;
case 'select':
if((param.value.data is map) || (param.value.data is list)){
<select name=(String.toLower(String.replace(param.key,' ','_'))) style=(param.value.style.form)>
<option value=""> "Select..."</option>
foreach(var option in param.value.data){
<option value=(option)> option </option>
}
</select>
}
break;
default:
// ignore.
break;
}
</td>
</tr>
}
<tr>
<td>
foreach(var param in params){
if(param.value.type!='hidden') continue;
<input type="hidden" name=(String.toLower(String.replace(param.key,' ','_'))) value=(param.value.data) />
}
</td>
<td align="right">
<input type="button" value="Submit" ctor="when($this.click) {
var m = { };
Deki.$('#' + {{@form}}).find('input, select, textarea').each(function() {
m[this.name] = Deki.$(this).val();
});
Deki.publish('default', m);
}" id="saveButton" />
</td>
</tr>
</tbody>
</table>
</form>
<script type="text/jem">"
var dapi = '/@api/deki/pages/=';
var dparams = '/contents?abort=never';
var dpath;
Deki.subscribe('default', null, function(c, m, d) { // listen for submit events.
// -- Modified by carles.coll 2010/12/27
// dpath = Deki.url.encode(M'"..page.path.."' + '/' + m['title'].replace(/ /g,'_'));*/
dpath = Deki.url.encode(MindTouch.Text.Utf8Encode('"..page.path.."' + '/' + m['title'].replace(/ /g,'_')));
var edpath = Deki.url.encode(Deki.url.encode(dpath));
// -- Modified by carles.coll 2010/12/27
// var ddata = ''<pre class=\\'script\\'> Ticket() </pre>'';
var ddata = '"..new_page_content.."';
Deki.$.ajax({
type: 'POST',
url: dapi+edpath+dparams,
data: ddata,
complete: function(xhr){
if(xhr.status == 200) saveTicket(dpath, m);
else if(xhr.status == 400) alert('Request already exists! Try again with a different title.');
else if(xhr.status == 403) alert('Permission denied. Log in and try again.');
else alert('Error ' + xhr.status);
}
});
}, null);
"</script>
<br /><br />
<div id="buttons-panel">
<input type="button" value="Export to CSV" ctor="
var self = $this;
$this.click(function() {
$({{'#'..@download}}).table2csv({
callback: function (csv, name) {
$('<div></div>')
.append($('<textarea></textarea>')
.css({'width':'500px','height':'400px'})
.text(csv))
.insertAfter('#buttons-panel')
.dialog({
height: 480,
width: 560
});
}
});
});
" />
<input type='button' value='Clear Filters' onclick="
Deki.$('table.display tfoot select, table.display tfoot input').each(function() {
Deki.$(this).val('');
oTable.fnFilter(Deki.$(this).val(),$('table.display tfoot th').index(Deki.$(this).parent()));
});
" />
</div>
<br /><br />
var data = page.subpages;
if(#data > 0) {
<table class="display" id=(@tickets) cellpadding="3" cellspacing="0" width="100%">
<thead>
<tr>
foreach(var param in params){
if(! param.value.show || param.value.show == 'both' || param.value.show == 'table'){
<th> param.value.label ?? String.ToCamelCase(param.key) </th>
}
}
</tr>
</thead>
<tbody>
foreach(var p in data){
var class="";
var props = p.properties;
if(list.contains(list.collect(params,'key'),'status')){
if(props.status.text && props.status.text != ''){
let class = String.replace(String.toLower(props.status.text)," ","");
}
else{
let class = "new";
}
}
<tr id=(props.id.text) class=(class)>
foreach(var param in params){
if(param.value.show && param.value.show == 'ticket') continue; // if not supposed to show in table, skip.
var property = Map.values(map.select(props, "$.key=='"..String.replace(String.toLower(param.key)," ","_").."'"))[0];
<td>
switch (param.value.type){
case 'datepicker':
if(param.key =='title'){
<a href=(p.uri) style=(param.value.style.table)>property.text</a>
}else{
<span style=(param.value.style.table)> property.text </span>
}
break;
case 'textarea':
<span style="display:none;"> property.text </span> // keep this here so that filtering sees the whole string, not just the first 50 chars.
if(#property.text >50){ // A string of over 50 characters is long. Don't show the whole thing.
if(param.key =='title'){
<a href=(p.uri) style=(param.value.style.table)>String.Substr(property.text,0,50).."..."</a>
}else{
<span style=(param.value.style.table)>String.Substr(property.text,0,50).."..."</span>
}
}
else{
if(param.key =='title'){
<a href=(p.uri) style=(param.value.style.table)>property.text</a>
}else{
<span style=(param.value.style.table)>property.text</span>
}
}
break;
default:
if(param.key =='title'){
<a href=(p.uri) style=(param.value.style.table)>property.text </a>
}else{
<span style=(param.value.style.table)>property.text</span>
}
break;
}
</td>
}
</tr>
}
</tbody>
<tfoot>
<tr>
// Allow filtering for lists and maps.
foreach(var param in params){
if(param.value.show && param.value.show == 'ticket') continue; //skip if not supposed to show in table.
if(param.value.data is list || param.value.data is map){
<th>
<select>
<option value=""> "Show only..." </option>
foreach(var option in param.value.data){
<option value=(option)>(option)</option>
}
</select>
</th>
}
else {
<th>
<input type="text" />
</th>
}
}
</tr>
</tfoot>
</table>
<table id=(@download) style="display:none">
<tbody>
<tr>
foreach(var param in params){
<td> param.value.label ?? String.ToCamelCase(param.key) </td>
}
</tr>
foreach(var p in data){
<tr>
var props = p.properties;
foreach(var param in params){
var property = Map.values(map.select(props, "$.key=='"..String.replace(String.toLower(param.key)," ","_").."'"));
let property = property[0];
<td>property.text</td>
}
</tr>
}
</tbody>
</table>
}
else {
"Table contains no data.";
}
| Version | Change |
|---|---|
| v2.7 | Added a suggestion field type. (Similar to Auto-complete) |
| v2.6 | Added a resizable option to textareas. Thanks graynotgrey! |
| v2.5 | Added even more customization (see here). Added more filtering options. |
| v2.0 | Added extreme customization options, added export to csv, fixed a bug where pages don't redirect properly if there are more than 1 space in the title. |
| v1.1 | Added dynamic options. Tickets now read the options from the parent page's options (i.e. - the TicketForm's options.) |
| v1.0 | Posted to this Wiki |
/**
Author: Blake Harms
Version: 2.7
See http://developer.mindtouch.com/DekiScript/FAQ/How_do_I..._Build_an_Integrated_Bug_and_Issue_Tracker for a changelog.
*/
dekiapi();
jquery.ui("smoothness");
// Gather options from parent (form)
var options = String.eval(page.parent.properties.options.text);
var params = string.deserialize(options.params);
<html><head>
<script type="text/javascript" src="http://developer.mindtouch.com/@api/deki/files/4634/=jquery.autocomplete.pack.js"></script>
<link rel="stylesheet" type="text/css" href="http://developer.mindtouch.com/@api/deki/files/4635/=jquery.autocomplete.css" />
<script type="text/javascript">"
Deki.$(document).ready(function() { //when the document is ready...
Deki.$('.datepicker').datepicker();
Deki.$('.resizable').resizable();
Deki.$('#ticketProperties').find('input, select,textarea').change(function(){
$self = Deki.$(this);
var prop = 'urn:custom.mindtouch.com#' + $self.attr('name'); // url that retrieves the page properties
Deki.Api.ReadPageProperty(null, prop, function(result) {
if(result.etag) { // page property exists, write over it.
Deki.Api.UpdatePageProperty(result.href, $self.val(), result.etag, function() {
reportSuccess($self);
}, function(result) {
alert('An error occurred trying to update the store (status: ' + result.status + ' - ' + result.text + ')');
});
} else { // page property doesn't exist, create one.
Deki.Api.CreatePageProperty(null, prop, $self.val(), function() {
reportSuccess($self);
}, function(result) {
alert('An error occurred trying to create the store (status: ' + result.status + ' - ' + result.text + ')');
});
}
}, function(result) {
alert('An error occurred trying to read the store (status: ' + result.status + ' - ' + result.text + ')');
});
});
});
"</script>
<script type="text/javascript">"
var reportSuccess = function($self) {
$self.addClass('value_updated');
setTimeout('$self.removeClass(\\'value_updated\\')',1000);
}
"</script>
<style type="text/css">"
#ticketProperties table { border-spacing:0;border-collapse:collapse; }
td.label { background-color:#F0F0F0; font-weight:bold; width:150px; }
.value_updated { background-color:#FFFFA7 !important; }
"</style>
</head></html>
<div id="top-nav-bar">
<a href=(page.parent.uri) class='to-table'> "Back to form" </a>
</div>
<div id="ticketProperties">
<table cellspacing="0" cellpadding="3" border="1" width="70%" style="table-layout: fixed;">
<tbody>
foreach(var param in params){
var type = param.value.type;
if(! type){
if(param.value.data is list || param.value is map) let type = 'select';
if(!param.value.data || param.value.data is str) let type = 'text';
}
if(param.value.show == 'table' || param.key=='title') continue; // skip if not supposed to be seen here.
<tr>
<td class="label"> param .value.label ?? String.toCamelCase(param .key) </td>
<td>
var property = Map.values(map.select(page.properties, "$.key=='"..String.replace(String.toLower(param .key)," ","_").."'"))[0];
if(param.value.editable !== false){
switch(type){
case 'suggest':
if(param.value.data is list){
<input type="text" name=(String.toLower(String.replace(param.key,' ','_'))) style=(param.value.style.form) value=(param.value.data) ctor=(
"$this.autocomplete("..JSON.emit(param.value.data)..");") />
}
break;
case 'text':
<input type="text" name=(String.toLower(String.replace(param.key,' ','_'))) style=(param.value.style.ticket) value=(property.text) />
break;
case 'textarea':
var resizable = (typeof param.value.resizable == typeof null || param.value.resizable) ? 'resizable' : '';
<textarea class=(resizable) name=(String.toLower(String.replace(param.key,' ','_'))) style=(param.value.style.ticket)>property.text</textarea>
break;
case 'datepicker':
<input type="text" class="datepicker" name=(String.toLower(String.replace(param.key,' ','_'))) style=(param.value.style.ticket) value=(property.text) />
break;
case 'hidden':
property.text;
break;
case 'title':
<input type="text" class="title" name=(String.toLower(String.replace(param.key,' ','_'))) style=(param.value.style.ticket) value=(param.value.data) />
break;
case 'status': // follow through.
case 'select':
if((param.value.data is map) || (param.value.data is list)){
<select name=(String.toLower(String.replace(param.key,' ','_'))) style=(param.value.style.ticket)>
<option value=(property.text)>property.text</option>
<option value=""> ""</option>
foreach(var option in param.value.data){
<option value=(option)> option </option>
}
</select>
}
else{
<span style=(param.value.style.ticket)>param.value.data</span>
}
break;
default: // ignore.
break;
}
}
else {
<span style=(param.value.style.ticket)>property.text</span>
}
</td>
</tr>
}
</tbody>
</table>
</div>
Note: this requires permission to save UNSAFECONTENT on your wiki.
Notice that there are images and Javascript files linked from other websites. If you want your Ticket system to be self-contained, you need to download those files to your computer and upload them somewhere on your wiki.
Here are some example of what a call to the TicketForm template looks like. You can call the template with no options to use the defaults like so:
{{ TicketForm(); }}
See usage for more information.
I hope to put the following in this already awesome template:
With version 2.0, many more features were added. For instance, you can easily manipulate this form into just about anything without changing the template.
| Parameter | Type | Description |
|---|---|---|
| options | map | (optional) allows for custom field creation. See here for customization tips. |
| new_page_content | string | (optional, by default: '<pre class=\\'script\\'> Ticket() </pre>' ) The content of the new subpage created . |
More tips here.
Here are some examples of types of systems you can create:Customization Tips
(Because you KNOW you want one...)
Now, this DOES NOT work entirely... yet. I still have to get the permission to add templates to make the tickets display properly... Anybody wanna make the templates for me?
There is an example of the Ticket at Example of a templated ticket
The TicketForm example has been moved.
I want to thank SteveB for providing the inspiration and assistance with setting up the TODO Template.
Everyone who has participated in the growth of this application by using and submitting bugs!
| File | Version | Size | Modified | |
|---|---|---|---|---|
| ||||
| ||||
| ||||
| ||||
| Images 0 | ||
|---|---|---|
| No images to display in the gallery. |
Copyright © 2011 MindTouch, Inc. Powered by
I am just trying out mindtouch and this bug tracking script.
I discovered a bug, but now I don't know if it's a mindtouch problem, or a problem due to this particular script.
On my wiki I created a page entitled "Problèmes utilistateurs" (user problems in French). Notice the accent on the letter 'e'.
The hyperlink to acces this page is http://mydeki.wiki/Informatique/Problèmes_utilisateur
Now I set up this bug tracking script on the "Problèmes utilisateurs" page. Here's the problem: when I add a ticket, it creates a new page like so: /Informatique/Probl%ef%bf%bdmes_utilisateur/ and another one /Informatique/Probl%ef%bf%bdmes_utilisateur/ticket_name
Both these pages contain the following text: Page title (Informatique/Probl�mes_utilisateur) is an invalid title - it contains illegal characters.
These pages cannot be deleted through the wiki interface.
How can I make several different versions with different formproperties of bugtracker? If I just copy two template and rename them it fails with errors. Is there some place in the code that you could define own template names for different forms?
for 1200 items this is a bit slow. Can anyone suggest how to speed it up?
I've got everything rendering - went through the whole template setup, ended up missing some of the extensions, got that going, and it's happy. But when I try to create a new issue, clicking submit gives me this message in IE:
Message: 'ddata' is undefined
Line: 362
Char: 9
Which appears to be directly related to this line:
Deki.$.ajax({
type: 'POST',
url: dapi+edpath+dparams,
data: ddata,
complete: function(xhr){
if(xhr.status == 200) saveTicket(dpath, m);
else if(xhr.status == 400) alert('Request already exists! Try again with a different title.');
else if(xhr.status == 403) alert('Permission denied. Log in and try again.');
else alert('Error ' + xhr.status);
}
});
I see that the 'var ddata' declaration directly above it is commented out, but uncommenting it just gives me an error about a missing semicolon.
Sorry for my noobish-ness on this; I haven't played with the AJAX stuff before, so it's very new territory.
I have exactly the same issue as jen.r.magas.
Just uncommenting the line gives another error as already mentioned above!
The code line looks like this:
// -- Modified by carles.coll 2010/12/27
// var ddata = ''<pre class=\\'script\\'> Ticket() </pre>'';
Works great!!!
The special character fix is so useful!!! I had to delete so many pages via the database, because they weren't accessible via wiki interface because of the german ä ö ü.
Good job Carles!
Carles.
Basically, we want to create a central task list logger but that each person can see in their own home page.
I'm not sure where I should start looking, but if I paste the code in a deki script block (in source mode), and save the page, for TicketForm I get:
"Callstack:
at Template:TicketForm
MindTouch.Deki.Script.Compiler.DekiScriptParserException: invalid XmlNode: pre, line 56, column 1"
For the Ticket template, I get something similar.
I see people mention that some extensions need to be installed, but these are not mentioned. Maybe this is at fault? Which extensions and other dependencies does this rely on? I'm working with a completely vanilla install of 10.1.0 edited 17:40, 28 Jul 2011