Fossil SCM

fossil-scm / src / tktsetup.c
Blame History Raw 1074 lines
1
/*
2
** Copyright (c) 2007 D. Richard Hipp
3
**
4
** This program is free software; you can redistribute it and/or
5
** modify it under the terms of the Simplified BSD License (also
6
** known as the "2-Clause License" or "FreeBSD License".)
7
8
** This program is distributed in the hope that it will be useful,
9
** but without any warranty; without even the implied warranty of
10
** merchantability or fitness for a particular purpose.
11
**
12
** Author contact information:
13
** [email protected]
14
** http://www.hwaci.com/drh/
15
**
16
*******************************************************************************
17
**
18
** This file contains code to implement the ticket configuration
19
** setup screens.
20
*/
21
#include "config.h"
22
#include "tktsetup.h"
23
#include <assert.h>
24
25
/*
26
** WEBPAGE: tktsetup
27
** Main sub-menu for configuring the ticketing system.
28
*/
29
void tktsetup_page(void){
30
login_check_credentials();
31
if( !g.perm.Setup ){
32
login_needed(0);
33
return;
34
}
35
36
style_header("Ticket Setup");
37
@ <table border="0" cellspacing="20">
38
setup_menu_entry("Table", "tktsetup_tab",
39
"Specify the schema of the \"ticket\" table in the database.");
40
setup_menu_entry("Timeline", "tktsetup_timeline",
41
"How to display ticket status in the timeline");
42
setup_menu_entry("Common", "tktsetup_com",
43
"Common TH1 code run before all ticket processing.");
44
setup_menu_entry("Change", "tktsetup_change",
45
"The TH1 code run after a ticket is edited or created.");
46
setup_menu_entry("New Ticket Page", "tktsetup_newpage",
47
"HTML with embedded TH1 code for the \"new ticket\" webpage.");
48
setup_menu_entry("View Ticket Page", "tktsetup_viewpage",
49
"HTML with embedded TH1 code for the \"view ticket\" webpage.");
50
setup_menu_entry("Edit Ticket Page", "tktsetup_editpage",
51
"HTML with embedded TH1 code for the \"edit ticket\" webpage.");
52
setup_menu_entry("Report List Page", "tktsetup_reportlist",
53
"HTML with embedded TH1 code for the \"report list\" webpage.");
54
setup_menu_entry("Report Template", "tktsetup_rpttplt",
55
"The default ticket report format.");
56
setup_menu_entry("Key Template", "tktsetup_keytplt",
57
"The default color key for reports.");
58
@ </table>
59
style_finish_page();
60
}
61
62
/*
63
** NOTE: When changing the table definition below, also change the
64
** equivalent definition found in schema.c.
65
*/
66
/* @-comment: ** */
67
static const char zDefaultTicketTable[] =
68
@ CREATE TABLE ticket(
69
@ -- Do not change any column that begins with tkt_
70
@ tkt_id INTEGER PRIMARY KEY,
71
@ tkt_uuid TEXT UNIQUE,
72
@ tkt_mtime DATE,
73
@ tkt_ctime DATE,
74
@ -- Add as many fields as required below this line
75
@ type TEXT,
76
@ status TEXT,
77
@ subsystem TEXT,
78
@ priority TEXT,
79
@ severity TEXT,
80
@ foundin TEXT,
81
@ private_contact TEXT,
82
@ resolution TEXT,
83
@ title TEXT,
84
@ comment TEXT
85
@ );
86
@ CREATE TABLE ticketchng(
87
@ -- Do not change any column that begins with tkt_
88
@ tkt_id INTEGER REFERENCES ticket,
89
@ tkt_rid INTEGER REFERENCES blob,
90
@ tkt_mtime DATE,
91
@ tkt_user TEXT,
92
@ -- Add as many fields as required below this line
93
@ login TEXT,
94
@ username TEXT,
95
@ mimetype TEXT,
96
@ icomment TEXT
97
@ );
98
@ CREATE INDEX ticketchng_idx1 ON ticketchng(tkt_id, tkt_mtime);
99
;
100
101
/*
102
** Return the ticket table definition in heap-allocated
103
** memory owned by the caller.
104
*/
105
char *ticket_table_schema(void){
106
return db_get("ticket-table", zDefaultTicketTable);
107
}
108
109
/*
110
** Common implementation for the ticket setup editor pages.
111
*/
112
static void tktsetup_generic(
113
const char *zTitle, /* Page title */
114
const char *zDbField, /* Configuration field being edited */
115
const char *zDfltValue, /* Default text value */
116
const char *zDesc, /* Description of this field */
117
char *(*xText)(const char*), /* Validity test or NULL */
118
void (*xRebuild)(void), /* Run after successful update */
119
int height /* Height of the edit box */
120
){
121
const char *z;
122
int isSubmit;
123
124
login_check_credentials();
125
if( !g.perm.Setup ){
126
login_needed(0);
127
return;
128
}
129
style_set_current_feature("tktsetup");
130
if( P("setup") ){
131
cgi_redirect("tktsetup");
132
}
133
isSubmit = P("submit")!=0;
134
z = P("x");
135
if( z==0 ){
136
z = db_get(zDbField, zDfltValue);
137
}
138
style_set_current_feature("tktsetup");
139
style_header("Edit %s", zTitle);
140
if( P("clear")!=0 && cgi_csrf_safe(2) ){
141
db_unset(zDbField/*works-like:"x"*/, 0);
142
if( xRebuild ) xRebuild();
143
cgi_redirect("tktsetup");
144
}else if( isSubmit && cgi_csrf_safe(2) ){
145
char *zErr = 0;
146
if( xText && (zErr = xText(z))!=0 ){
147
@ <p class="tktsetupError">ERROR: %h(zErr)</p>
148
}else{
149
db_set(zDbField/*works-like:"x"*/, z, 0);
150
if( xRebuild ) xRebuild();
151
cgi_redirect("tktsetup");
152
}
153
}
154
@ <form action="%R/%s(g.zPath)" method="post"><div>
155
login_insert_csrf_secret();
156
@ <p>%s(zDesc)</p>
157
@ <textarea name="x" rows="%d(height)" cols="80">%h(z)</textarea>
158
@ <blockquote><p>
159
@ <input type="submit" name="submit" value="Apply Changes">
160
@ <input type="submit" name="clear" value="Revert To Default">
161
@ <input type="submit" name="setup" value="Cancel">
162
@ </p></blockquote>
163
@ </div></form>
164
@ <hr>
165
@ <h2>Default %s(zTitle)</h2>
166
@ <blockquote><pre>
167
@ %h(zDfltValue)
168
@ </pre></blockquote>
169
style_submenu_element("Back", "%R/tktsetup");
170
style_finish_page();
171
}
172
173
/*
174
** WEBPAGE: tktsetup_tab
175
** Administrative page for defining the "ticket" table used
176
** to hold ticket information.
177
*/
178
void tktsetup_tab_page(void){
179
static const char zDesc[] =
180
@ Enter a valid CREATE TABLE statement for the "ticket" table. The
181
@ table must contain columns named "tkt_id", "tkt_uuid", and "tkt_mtime"
182
@ with an unique index on "tkt_uuid" and "tkt_mtime".
183
;
184
tktsetup_generic(
185
"Ticket Table Schema",
186
"ticket-table",
187
zDefaultTicketTable,
188
zDesc,
189
ticket_schema_check,
190
ticket_rebuild,
191
20
192
);
193
}
194
195
static const char zDefaultTicketCommon[] =
196
@ set type_choices {
197
@ Code_Defect
198
@ Build_Problem
199
@ Documentation
200
@ Feature_Request
201
@ Incident
202
@ }
203
@ set priority_choices {
204
@ Immediate
205
@ High
206
@ Medium
207
@ Low
208
@ Zero
209
@ }
210
@ set severity_choices {
211
@ Critical
212
@ Severe
213
@ Important
214
@ Minor
215
@ Cosmetic
216
@ }
217
@ set resolution_choices {
218
@ Open
219
@ Fixed
220
@ Rejected
221
@ Workaround
222
@ Unable_To_Reproduce
223
@ Works_As_Designed
224
@ External_Bug
225
@ Not_A_Bug
226
@ Duplicate
227
@ Overcome_By_Events
228
@ Drive_By_Patch
229
@ Misconfiguration
230
@ }
231
@ set status_choices {
232
@ Open
233
@ Verified
234
@ Review
235
@ Deferred
236
@ Fixed
237
@ Tested
238
@ Closed
239
@ }
240
@ set subsystem_choices {
241
@ }
242
;
243
244
/*
245
** Return the ticket common code.
246
*/
247
const char *ticket_common_code(void){
248
return db_get("ticket-common", zDefaultTicketCommon);
249
}
250
251
/*
252
** WEBPAGE: tktsetup_com
253
** Administrative page used to define TH1 script that is
254
** common to all ticket screens.
255
*/
256
void tktsetup_com_page(void){
257
static const char zDesc[] =
258
@ Enter TH1 script that initializes variables prior to generating
259
@ any of the ticket view, edit, or creation pages.
260
;
261
tktsetup_generic(
262
"Ticket Common Script",
263
"ticket-common",
264
zDefaultTicketCommon,
265
zDesc,
266
0,
267
0,
268
30
269
);
270
}
271
272
static const char zDefaultTicketChange[] =
273
@ return
274
;
275
276
/*
277
** Return the ticket change code.
278
*/
279
const char *ticket_change_code(void){
280
return db_get("ticket-change", zDefaultTicketChange);
281
}
282
283
/*
284
** WEBPAGE: tktsetup_change
285
** Administrative screen used to view or edit the TH1 script
286
** that shows ticket changes.
287
*/
288
void tktsetup_change_page(void){
289
static const char zDesc[] =
290
@ Enter TH1 script that runs after processing the ticket editing
291
@ and creation pages.
292
;
293
tktsetup_generic(
294
"Ticket Change Script",
295
"ticket-change",
296
zDefaultTicketChange,
297
zDesc,
298
0,
299
0,
300
30
301
);
302
}
303
304
static const char zDefaultNew[] =
305
@ <th1>
306
@ if {![info exists mutype]} {set mutype Markdown}
307
@ if {[info exists submit] || [info exists submitandnew]} {
308
@ set status Open
309
@ if {$mutype eq "HTML"} {
310
@ set mimetype "text/html"
311
@ } elseif {$mutype eq "Wiki"} {
312
@ set mimetype "text/x-fossil-wiki"
313
@ } elseif {$mutype eq "Markdown"} {
314
@ set mimetype text/x-markdown
315
@ } elseif {$mutype eq {[links only]}} {
316
@ set mimetype "text/x-fossil-plain"
317
@ } else {
318
@ set mimetype "text/plain"
319
@ }
320
@ submit_ticket
321
@ set preview 1
322
@ }
323
@ </th1>
324
@ <h1 style="text-align: center;">Enter A New Ticket</h1>
325
@ <table cellpadding="5">
326
@ <tr>
327
@ <td colspan="3">
328
@ Enter a one-line summary of the ticket:<br>
329
@ <input type="text" name="title" size="60" value="$<title>">
330
@ </td>
331
@ </tr>
332
@
333
@ <tr>
334
@ <td align="right">Type:</td>
335
@ <td align="left"><th1>combobox type $type_choices 1</th1></td>
336
@ <td align="left">What type of ticket is this?</td>
337
@ </tr>
338
@
339
@ <tr>
340
@ <td align="right">Version:</td>
341
@ <td align="left">
342
@ <input type="text" name="foundin" size="20" value="$<foundin>">
343
@ </td>
344
@ <td align="left">In what version or build number do you observe
345
@ the problem?</td>
346
@ </tr>
347
@
348
@ <tr>
349
@ <td align="right">Severity:</td>
350
@ <td align="left"><th1>combobox severity $severity_choices 1</th1></td>
351
@ <td align="left">How debilitating is the problem? How badly does the problem
352
@ affect the operation of the product?</td>
353
@ </tr>
354
@
355
@ <th1>
356
@ if {[capexpr {w}]} {
357
@ html {<tr><td class="tktDspLabel">Priority:</td><td>}
358
@ combobox priority $priority_choices 1
359
@ html {
360
@ <td align="left">How important is the affected functionality?</td>
361
@ </td></tr>
362
@ }
363
@
364
@ html {<tr><td class="tktDspLabel">Subsystem:</td><td>}
365
@ combobox subsystem $subsystem_choices 1
366
@ html {
367
@ <td align="left">Which subsystem is affected?</td>
368
@ </td></tr>
369
@ }
370
@ }
371
@ </th1>
372
@
373
@ <tr>
374
@ <td align="right">EMail:</td>
375
@ <td align="left">
376
@ <input name="private_contact" value="$<private_contact>" size="30">
377
@ </td>
378
@ <td align="left"><u>Not publicly visible</u>
379
@ Used by developers to contact you with questions.</td>
380
@ </tr>
381
@
382
@ <tr>
383
@ <td colspan="3">
384
@ Enter a detailed description of the problem.
385
@ For code defects, be sure to provide details on exactly how
386
@ the problem can be reproduced. Provide as much detail as
387
@ possible. Format:
388
@ <th1>combobox mutype {HTML {[links only]} Markdown {Plain Text} Wiki} 1</th1>
389
@ <br>
390
@ <th1>set nline [linecount $comment 50 10]</th1>
391
@ <textarea name="icomment" cols="80" rows="$nline"
392
@ wrap="virtual" class="wikiedit">$<icomment></textarea><br>
393
@ </tr>
394
@
395
@ <th1>enable_output [info exists preview]</th1>
396
@ <tr><td colspan="3">
397
@ Description Preview:<br><hr>
398
@ <th1>
399
@ if {$mutype eq "Wiki"} {
400
@ wiki $icomment
401
@ } elseif {$mutype eq "Plain Text"} {
402
@ set r [randhex]
403
@ wiki "<verbatim-$r>[string trimright $icomment]\n</verbatim-$r>"
404
@ } elseif {$mutype eq "Markdown"} {
405
@ html [lindex [markdown "$icomment\n"] 1]
406
@ } elseif {$mutype eq {[links only]}} {
407
@ set r [randhex]
408
@ wiki "<verbatim-$r links>[string trimright $icomment]\n</verbatim-$r>"
409
@ } else {
410
@ wiki "<nowiki>$icomment\n</nowiki>"
411
@ }
412
@ </th1>
413
@ <hr></td></tr>
414
@ <th1>enable_output 1</th1>
415
@
416
@ <tr>
417
@ <td><td align="left">
418
@ <input type="submit" name="preview" value="Preview">
419
@ </td>
420
@ <td align="left">See how the description will appear after formatting.</td>
421
@ </tr>
422
@
423
@ <th1>enable_output [info exists preview]</th1>
424
@ <tr>
425
@ <td><td align="left">
426
@ <input type="submit" name="submit" value="Submit">
427
@ </td>
428
@ <td align="left">After filling in the information above, press this
429
@ button to create the new ticket.</td>
430
@ </tr>
431
@
432
@ <tr>
433
@ <td><td align="left">
434
@ <input type="submit" name="submitandnew" value="Submit and New">
435
@ </td>
436
@ <td align="left">Create the new ticket and start another
437
@ ticket form with the inputs.</td>
438
@ </tr>
439
@ <th1>enable_output 1</th1>
440
@
441
@ <tr>
442
@ <td><td align="left">
443
@ <input type="submit" name="cancel" value="Cancel">
444
@ </td>
445
@ <td>Abandon and forget this ticket.</td>
446
@ </tr>
447
@ </table>
448
;
449
450
/*
451
** Return the code used to generate the new ticket page
452
*/
453
const char *ticket_newpage_code(void){
454
return db_get("ticket-newpage", zDefaultNew);
455
}
456
457
/*
458
** WEBPAGE: tktsetup_newpage
459
** Administrative page used to view or edit the TH1 script used
460
** to enter new tickets.
461
*/
462
void tktsetup_newpage_page(void){
463
static const char zDesc[] =
464
@ Enter HTML with embedded TH1 script that will render the "new ticket"
465
@ page
466
;
467
tktsetup_generic(
468
"HTML For New Tickets",
469
"ticket-newpage",
470
zDefaultNew,
471
zDesc,
472
0,
473
0,
474
40
475
);
476
}
477
478
static const char zDefaultView[] =
479
@ <table cellpadding="5">
480
@ <tr><td class="tktDspLabel">Ticket&nbsp;Hash:</td>
481
@ <th1>
482
@ if {[info exists tkt_uuid]} {
483
@ html "<td class='tktDspValue' colspan='3'>"
484
@ copybtn hash-tk 0 $tkt_uuid 2
485
@ if {[hascap s]} {
486
@ puts " ($tkt_id)"
487
@ }
488
@ html "</td></tr>\n"
489
@ } else {
490
@ if {[hascap s]} {
491
@ html "<td class='tktDspValue' colspan='3'>Deleted "
492
@ html "(0)</td></tr>\n"
493
@ } else {
494
@ html "<td class='tktDspValue' colspan='3'>Deleted</td></tr>\n"
495
@ }
496
@ }
497
@
498
@ if {[capexpr {n}]} {
499
@ submenu link "Copy Ticket" $baseurl/tktnew/$tkt_uuid
500
@ }
501
@ if {[capexpr {nk}]} {
502
@ submenu link "Edit Wiki" $baseurl/wikiedit?name=ticket/$tkt_uuid
503
@ }
504
@ </th1>
505
@ <tr><td class="tktDspLabel">Title:</td>
506
@ <td class="tktDspValue" colspan="3">
507
@ $<title>
508
@ </td></tr>
509
@ <tr><td class="tktDspLabel">Status:</td><td class="tktDspValue">
510
@ $<status>
511
@ </td>
512
@ <td class="tktDspLabel">Type:</td><td class="tktDspValue">
513
@ $<type>
514
@ </td></tr>
515
@ <tr><td class="tktDspLabel">Severity:</td><td class="tktDspValue">
516
@ $<severity>
517
@ </td>
518
@ <td class="tktDspLabel">Priority:</td><td class="tktDspValue">
519
@ $<priority>
520
@ </td></tr>
521
@ <tr><td class="tktDspLabel">Subsystem:</td><td class="tktDspValue">
522
@ $<subsystem>
523
@ </td>
524
@ <td class="tktDspLabel">Resolution:</td><td class="tktDspValue">
525
@ $<resolution>
526
@ </td></tr>
527
@ <tr><td class="tktDspLabel">Last&nbsp;Modified:</td><td class="tktDspValue">
528
@ <th1>
529
@ if {[info exists tkt_datetime]} {
530
@ puts $tkt_datetime
531
@ }
532
@ if {[info exists tkt_mage]} {
533
@ html "<br>[htmlize $tkt_mage] ago"
534
@ }
535
@ </th1>
536
@ </td>
537
@ <td class="tktDspLabel">Created:</td><td class="tktDspValue">
538
@ <th1>
539
@ if {[info exists tkt_datetime_creation]} {
540
@ puts $tkt_datetime_creation
541
@ }
542
@ if {[info exists tkt_cage]} {
543
@ html "<br>[htmlize $tkt_cage] ago"
544
@ }
545
@ </th1>
546
@ </td></tr>
547
@ <th1>enable_output [hascap e]</th1>
548
@ <tr>
549
@ <td class="tktDspLabel">Contact:</td><td class="tktDspValue" colspan="3">
550
@ $<private_contact>
551
@ </td>
552
@ </tr>
553
@ <th1>enable_output 1</th1>
554
@ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td>
555
@ <td colspan="3" valign="top" class="tktDspValue">
556
@ <th1>
557
@ set versionlink ""
558
@ set urlfoundin [httpize $foundin]
559
@ set tagpattern {^[-0-9A-Za-z_\\.]+$}
560
@ if [regexp $tagpattern $foundin] {
561
@ query {SELECT count(*) AS match FROM tag
562
@ WHERE tagname=concat('sym-',$foundin)} {
563
@ if {$match} {set versionlink "timeline?t=$urlfoundin"}
564
@ }
565
@ }
566
@ set hashpattern {^[0-9a-f]+$}
567
@ if [regexp $hashpattern $foundin] {
568
@ set pattern $foundin*
569
@ query {SELECT count(*) AS match FROM blob WHERE uuid GLOB $pattern} {
570
@ if {$match} {set versionlink "info/$urlfoundin"}
571
@ }
572
@ }
573
@ if {$versionlink eq ""} {
574
@ puts $foundin
575
@ } else {
576
@ html "<a href=\""
577
@ puts $versionlink
578
@ html "\">"
579
@ puts $foundin
580
@ html "</a>"
581
@ }
582
@ </th1>
583
@ </td></tr>
584
@ </table>
585
@
586
@ <th1>
587
@ wiki_assoc "ticket" $tkt_uuid
588
@ </th1>
589
@
590
@ <table cellpadding="5" style="min-width:100%">
591
@ <th1>
592
@ if {[info exists comment]} {
593
@ if {[string length $comment]>10} {
594
@ html {
595
@ <tr><td class="tktDspLabel">Description:</td></tr>
596
@ <tr><td colspan="5" class="tktDspValue">
597
@ }
598
@ if {[info exists plaintext]} {
599
@ set r [randhex]
600
@ wiki "<verbatim-$r links>\n$comment\n</verbatim-$r>"
601
@ } else {
602
@ wiki $comment
603
@ }
604
@ }
605
@ }
606
@ set seenRow 0
607
@ set alwaysPlaintext [info exists plaintext]
608
@ query {SELECT datetime(tkt_mtime,toLocal()) AS xdate, login AS xlogin,
609
@ mimetype as xmimetype, icomment AS xcomment,
610
@ username AS xusername
611
@ FROM ticketchng
612
@ WHERE tkt_id=$tkt_id AND length(icomment)>0} {
613
@ if {$seenRow} {
614
@ html "<hr>\n"
615
@ } else {
616
@ html "<tr><td class='tktDspLabel' style='text-align:left'>\n"
617
@ html "User Comments:</td></tr>\n"
618
@ html "<tr><td colspan='5' class='tktDspValue'><div class='tktCommentArea'>\n"
619
@ set seenRow 1
620
@ }
621
@ html "<div class='tktCommentEntry'>"
622
@ html "<span class='tktDspCommenter'>"
623
@ puts $xlogin
624
@ if {$xlogin ne $xusername && [string length $xusername]>0} {
625
@ puts " (claiming to be $xusername)"
626
@ }
627
@ puts " added on $xdate:"
628
@ html "</span>\n"
629
@ if {$alwaysPlaintext || $xmimetype eq "text/plain"} {
630
@ set r [randhex]
631
@ if {$xmimetype ne "text/plain"} {puts "($xmimetype)\n"}
632
@ wiki "<verbatim-$r>[string trimright $xcomment]</verbatim-$r>\n"
633
@ } elseif {$xmimetype eq "text/x-fossil-wiki"} {
634
@ wiki "<p>\n[string trimright $xcomment]\n</p>\n"
635
@ } elseif {$xmimetype eq "text/x-markdown"} {
636
@ html [lindex [markdown $xcomment] 1]
637
@ } elseif {$xmimetype eq "text/html"} {
638
@ wiki "<p><nowiki>\n[string trimright $xcomment]\n</nowiki>\n"
639
@ } else {
640
@ set r [randhex]
641
@ wiki "<verbatim-$r links>[string trimright $xcomment]</verbatim-$r>\n"
642
@ }
643
@ html "</div>"; # .tktCommentEntry
644
@ }
645
@ if {$seenRow} {html "</div></td></tr>\n"}
646
@ </th1>
647
@ </table>
648
;
649
650
651
/*
652
** Return the code used to generate the view ticket page
653
*/
654
const char *ticket_viewpage_code(void){
655
return db_get("ticket-viewpage", zDefaultView);
656
}
657
658
/*
659
** WEBPAGE: tktsetup_viewpage
660
** Administrative page used to view or edit the TH1 script that
661
** displays individual tickets.
662
*/
663
void tktsetup_viewpage_page(void){
664
static const char zDesc[] =
665
@ Enter HTML with embedded TH1 script that will render the "view ticket" page
666
;
667
tktsetup_generic(
668
"HTML For Viewing Tickets",
669
"ticket-viewpage",
670
zDefaultView,
671
zDesc,
672
0,
673
0,
674
40
675
);
676
}
677
678
static const char zDefaultEdit[] =
679
@ <th1>
680
@ if {![info exists mutype]} {set mutype Markdown}
681
@ if {![info exists icomment]} {set icomment {}}
682
@ if {![info exists username]} {set username $login}
683
@ if {[info exists submit]} {
684
@ if {$mutype eq "Wiki"} {
685
@ set mimetype text/x-fossil-wiki
686
@ } elseif {$mutype eq "Markdown"} {
687
@ set mimetype text/x-markdown
688
@ } elseif {$mutype eq "HTML"} {
689
@ set mimetype text/html
690
@ } elseif {$mutype eq {[links only]}} {
691
@ set mimetype text/x-fossil-plain
692
@ } else {
693
@ set mimetype text/plain
694
@ }
695
@ submit_ticket
696
@ set preview 1
697
@ }
698
@ </th1>
699
@ <table cellpadding="5">
700
@ <tr><td class="tktDspLabel">Title:</td><td>
701
@ <input type="text" name="title" value="$<title>" size="60">
702
@ </td></tr>
703
@
704
@ <tr><td class="tktDspLabel">Status:</td><td>
705
@ <th1>combobox status $status_choices 1</th1>
706
@ </td></tr>
707
@
708
@ <tr><td class="tktDspLabel">Type:</td><td>
709
@ <th1>combobox type $type_choices 1</th1>
710
@ </td></tr>
711
@
712
@ <tr><td class="tktDspLabel">Severity:</td><td>
713
@ <th1>combobox severity $severity_choices 1</th1>
714
@ </td></tr>
715
@
716
@ <tr><td class="tktDspLabel">Priority:</td><td>
717
@ <th1>combobox priority $priority_choices 1</th1>
718
@ </td></tr>
719
@
720
@ <tr><td class="tktDspLabel">Resolution:</td><td>
721
@ <th1>combobox resolution $resolution_choices 1</th1>
722
@ </td></tr>
723
@
724
@ <tr><td class="tktDspLabel">Subsystem:</td><td>
725
@ <th1>combobox subsystem $subsystem_choices 1</th1>
726
@ </td></tr>
727
@
728
@ <th1>enable_output [hascap e]</th1>
729
@ <tr><td class="tktDspLabel">Contact:</td><td>
730
@ <input type="text" name="private_contact" size="40"
731
@ value="$<private_contact>">
732
@ </td></tr>
733
@ <th1>enable_output 1</th1>
734
@
735
@ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td><td>
736
@ <input type="text" name="foundin" size="50" value="$<foundin>">
737
@ </td></tr>
738
@
739
@ <tr><td colspan="2">
740
@ Append Remark with format
741
@ <th1>combobox mutype {HTML {[links only]} Markdown {Plain Text} Wiki} 1</th1>
742
@ from
743
@ <input type="text" name="username" value="$<username>" size="30">:<br>
744
@ <textarea name="icomment" cols="80" rows="15"
745
@ wrap="virtual" class="wikiedit">$<icomment></textarea>
746
@ </td></tr>
747
@
748
@ <th1>enable_output [info exists preview]</th1>
749
@ <tr><td colspan="2">
750
@ Description Preview:<br><hr>
751
@ <th1>
752
@ if {$mutype eq "Wiki"} {
753
@ wiki $icomment
754
@ } elseif {$mutype eq "Plain Text"} {
755
@ set r [randhex]
756
@ wiki "<verbatim-$r>\n[string trimright $icomment]\n</verbatim-$r>"
757
@ } elseif {$mutype eq "Markdown"} {
758
@ html [lindex [markdown "$icomment\n"] 1]
759
@ } elseif {$mutype eq {[links only]}} {
760
@ set r [randhex]
761
@ wiki "<verbatim-$r links>\n[string trimright $icomment]</verbatim-$r>"
762
@ } else {
763
@ wiki "<nowiki>\n[string trimright $icomment]\n</nowiki>"
764
@ }
765
@ </th1>
766
@ <hr>
767
@ </td></tr>
768
@ <th1>enable_output 1</th1>
769
@
770
@ <tr>
771
@ <td align="right">
772
@ <input type="submit" name="preview" value="Preview">
773
@ </td>
774
@ <td align="left">See how the description will appear after formatting.</td>
775
@ </tr>
776
@
777
@ <th1>enable_output [info exists preview]</th1>
778
@ <tr>
779
@ <td align="right">
780
@ <input type="submit" name="submit" value="Submit">
781
@ </td>
782
@ <td align="left">Apply the changes shown above</td>
783
@ </tr>
784
@ <th1>enable_output 1</th1>
785
@
786
@ <tr>
787
@ <td align="right">
788
@ <input type="submit" name="cancel" value="Cancel">
789
@ </td>
790
@ <td>Abandon this edit</td>
791
@ </tr>
792
@
793
@ <th1>
794
@ set seenRow 0
795
@ set alwaysPlaintext [info exists plaintext]
796
@ query {SELECT datetime(tkt_mtime,toLocal()) AS xdate, login AS xlogin,
797
@ mimetype as xmimetype, icomment AS xcomment,
798
@ username AS xusername
799
@ FROM ticketchng
800
@ WHERE tkt_id=$tkt_id AND length(icomment)>0} {
801
@ if {$seenRow} {
802
@ html "<hr>\n"
803
@ } else {
804
@ html "<tr><td colspan='2'><hr></td></tr>\n"
805
@ html "<tr><td colspan='2' class='tktDspLabel' style='text-align:left'>\n"
806
@ html "Previous User Comments:</td></tr>\n"
807
@ html "<tr><td colspan='2' class='tktDspValue'><div class='tktCommentArea'>\n"
808
@ set seenRow 1
809
@ }
810
@ html "<div class='tktCommentEntry'>"
811
@ html "<span class='tktDspCommenter'>"
812
@ puts $xlogin
813
@ if {$xlogin ne $xusername && [string length $xusername]>0} {
814
@ puts " (claiming to be $xusername)"
815
@ }
816
@ puts " added on $xdate:"
817
@ html "</span>\n"
818
@ if {$alwaysPlaintext || $xmimetype eq "text/plain"} {
819
@ set r [randhex]
820
@ if {$xmimetype ne "text/plain"} {puts "($xmimetype)\n"}
821
@ wiki "<verbatim-$r>[string trimright $xcomment]</verbatim-$r>\n"
822
@ } elseif {$xmimetype eq "text/x-fossil-wiki"} {
823
@ wiki "<p>\n[string trimright $xcomment]\n</p>\n"
824
@ } elseif {$xmimetype eq "text/x-markdown"} {
825
@ html [lindex [markdown $xcomment] 1]
826
@ } elseif {$xmimetype eq "text/html"} {
827
@ wiki "<p><nowiki>\n[string trimright $xcomment]\n</nowiki>\n"
828
@ } else {
829
@ set r [randhex]
830
@ wiki "<verbatim-$r links>[string trimright $xcomment]</verbatim-$r>\n"
831
@ }
832
@ html "</div>"; # .tktCommentEntry
833
@ }
834
@ if {$seenRow} {html "</div></td></tr>\n"}
835
@ </th1>
836
@
837
@ </table>
838
;
839
840
/*
841
** Return the code used to generate the edit ticket page
842
*/
843
const char *ticket_editpage_code(void){
844
return db_get("ticket-editpage", zDefaultEdit);
845
}
846
847
/*
848
** WEBPAGE: tktsetup_editpage
849
** Administrative page for viewing or editing the TH1 script that
850
** drives the ticket editing page.
851
*/
852
void tktsetup_editpage_page(void){
853
static const char zDesc[] =
854
@ Enter HTML with embedded TH1 script that will render the "edit ticket" page
855
;
856
tktsetup_generic(
857
"HTML For Editing Tickets",
858
"ticket-editpage",
859
zDefaultEdit,
860
zDesc,
861
0,
862
0,
863
40
864
);
865
}
866
867
/*
868
** The default report list page
869
*/
870
static const char zDefaultReportList[] =
871
@ <th1>
872
@ if {[anoncap n]} {
873
@ html "<p>Enter a new ticket:</p>"
874
@ html "<ul><li><a href='tktnew'>New ticket</a></li></ul>"
875
@ }
876
@ </th1>
877
@
878
@ <p>Choose a report format from the following list:</p>
879
@ <ol>
880
@ <th1>html $report_items</th1>
881
@ </ol>
882
@
883
@ <th1>
884
@ if {[anoncap t q]} {
885
@ html "<p>Other options:</p>\n<ul>\n"
886
@ if {[anoncap t]} {
887
@ html "<li><a href='rptnew'>New report format</a></li>\n"
888
@ }
889
@ if {[anoncap q]} {
890
@ html "<li><a href='modreq'>Tend to pending moderation requests</a></li>\n"
891
@ }
892
@ }
893
@ </th1>
894
;
895
896
/*
897
** Return the code used to generate the report list
898
*/
899
const char *ticket_reportlist_code(void){
900
return db_get("ticket-reportlist", zDefaultReportList);
901
}
902
903
/*
904
** WEBPAGE: tktsetup_reportlist
905
** Administrative page used to view or edit the TH1 script that
906
** defines the "report list" page.
907
*/
908
void tktsetup_reportlist(void){
909
static const char zDesc[] =
910
@ Enter HTML with embedded TH1 script that will render the "report list" page
911
;
912
tktsetup_generic(
913
"HTML For Report List",
914
"ticket-reportlist",
915
zDefaultReportList,
916
zDesc,
917
0,
918
0,
919
40
920
);
921
}
922
923
/*
924
** The default template ticket report format:
925
*/
926
static char zDefaultReport[] =
927
@ SELECT
928
@ CASE WHEN status IN ('Open','Verified') THEN '#f2dcdc'
929
@ WHEN status='Review' THEN '#e8e8e8'
930
@ WHEN status='Fixed' THEN '#cfe8bd'
931
@ WHEN status='Tested' THEN '#bde5d6'
932
@ WHEN status='Deferred' THEN '#cacae5'
933
@ ELSE '#c8c8c8' END AS 'bgcolor',
934
@ substr(tkt_uuid,1,10) AS '#',
935
@ datetime(tkt_ctime,toLocal()) AS 'created',
936
@ datetime(tkt_mtime,toLocal()) AS 'modified',
937
@ type,
938
@ status,
939
@ subsystem,
940
@ title,
941
@ comment AS '_comments'
942
@ FROM ticket
943
;
944
945
946
/*
947
** Return the template ticket report format:
948
*/
949
char *ticket_report_template(void){
950
return db_get("ticket-report-template", zDefaultReport);
951
}
952
953
/*
954
** WEBPAGE: tktsetup_rpttplt
955
**
956
** Administrative page used to view or edit the ticket report
957
** template.
958
*/
959
void tktsetup_rpttplt_page(void){
960
static const char zDesc[] =
961
@ Enter the default ticket report format template. This is the
962
@ template report format that initially appears when creating a
963
@ new ticket summary report.
964
;
965
tktsetup_generic(
966
"Default Report Template",
967
"ticket-report-template",
968
zDefaultReport,
969
zDesc,
970
0,
971
0,
972
20
973
);
974
}
975
976
/*
977
** The default template ticket key:
978
*/
979
static const char zDefaultKey[] =
980
@ #ffffff Key:
981
@ #f2dcdc Active
982
@ #e8e8e8 Review
983
@ #cfe8bd Fixed
984
@ #bde5d6 Tested
985
@ #cacae5 Deferred
986
@ #c8c8c8 Closed
987
;
988
989
990
/*
991
** Return the template ticket report format:
992
*/
993
const char *ticket_key_template(void){
994
return db_get("ticket-key-template", zDefaultKey);
995
}
996
997
/*
998
** WEBPAGE: tktsetup_keytplt
999
**
1000
** Administrative page used to view or edit the Key template
1001
** for tickets.
1002
*/
1003
void tktsetup_keytplt_page(void){
1004
static const char zDesc[] =
1005
@ Enter the default ticket report color-key template. This is the
1006
@ the color-key that initially appears when creating a
1007
@ new ticket summary report.
1008
;
1009
tktsetup_generic(
1010
"Default Report Color-Key Template",
1011
"ticket-key-template",
1012
zDefaultKey,
1013
zDesc,
1014
0,
1015
0,
1016
10
1017
);
1018
}
1019
1020
/*
1021
** WEBPAGE: tktsetup_timeline
1022
**
1023
** Administrative page used to configure how tickets are
1024
** rendered on timeline views.
1025
*/
1026
void tktsetup_timeline_page(void){
1027
login_check_credentials();
1028
if( !g.perm.Setup ){
1029
login_needed(0);
1030
return;
1031
}
1032
1033
if( P("setup") ){
1034
cgi_redirect("tktsetup");
1035
}
1036
style_set_current_feature("tktsetup");
1037
style_header("Ticket Display On Timelines");
1038
db_begin_transaction();
1039
@ <form action="%R/tktsetup_timeline" method="post"><div>
1040
login_insert_csrf_secret();
1041
1042
@ <hr>
1043
entry_attribute("Ticket Title", 40, "ticket-title-expr", "t",
1044
"title", 0);
1045
@ <p>An SQL expression in a query against the TICKET table that will
1046
@ return the title of the ticket for display purposes.
1047
@ (Property: ticket-title-expr)</p>
1048
1049
@ <hr>
1050
entry_attribute("Ticket Status", 40, "ticket-status-column", "s",
1051
"status", 0);
1052
@ <p>The name of the column in the TICKET table that contains the ticket
1053
@ status in human-readable form. Case sensitive.
1054
@ (Property: ticket-status-column)</p>
1055
1056
@ <hr>
1057
entry_attribute("Ticket Closed", 40, "ticket-closed-expr", "c",
1058
"status='Closed'", 0);
1059
@ <p>An SQL expression that evaluates to true in a TICKET table query if
1060
@ the ticket is closed.
1061
@ (Property: ticket-closed-expr)</p>
1062
1063
@ <hr>
1064
@ <p>
1065
@ <input type="submit" name="submit" value="Apply Changes">
1066
@ <input type="submit" name="setup" value="Cancel">
1067
@ </p>
1068
@ </div></form>
1069
db_end_transaction(0);
1070
style_submenu_element("Back", "%R/tktsetup");
1071
style_finish_page();
1072
1073
}
1074

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button