Overview
SHA1 Hash: | 5f3ddcc1b80bc8e20a09be8ff131522caa5d9359 |
---|---|
Date: | 2007-11-25 21:11:33 |
User: | drh |
Comment: | Add ticket configuration editing capability. |
Timelines: | ancestors | descendants | both | trunk |
Other Links: | files | ZIP archive | manifest |
Tags And Properties
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
Changes
[hide diffs]Modified src/setup.c from [9f3fedc058] to [ecaf658269].
@@ -38,18 +38,17 @@ void setup_menu_entry( const char *zTitle, const char *zLink, const char *zDesc ){ - @ <dt> + @ <tr><td valign="top" align="right"> if( zLink && zLink[0] ){ @ <a href="%s(zLink)">%h(zTitle)</a> }else{ @ %h(zTitle) } - @ </dt> - @ <dd>%h(zDesc)</dd> + @ </td><td valign="top">%h(zDesc)</td></tr> } /* ** WEBPAGE: /setup */ @@ -58,26 +57,26 @@ if( !g.okSetup ){ login_needed(); } style_header("Setup"); - @ <dl id="setup"> + @ <table border="0" cellspacing="20"> setup_menu_entry("Users", "setup_ulist", "Grant privileges to individual users."); setup_menu_entry("Access", "setup_access", "Control access settings."); setup_menu_entry("Configuration", "setup_config", "Configure the WWW components of the repository"); - setup_menu_entry("Tickets", "tktsetup", + setup_menu_entry("Tickets", "setup_ticket", "Configure the trouble-ticketing system for this repository"); setup_menu_entry("CSS", "setup_editcss", "Edit the Cascading Style Sheet used by all pages of this repository"); setup_menu_entry("Header", "setup_header", "Edit HTML text inserted at the top of every page"); setup_menu_entry("Footer", "setup_footer", "Edit HTML text inserted at the bottom of every page"); - @ </dl> + @ </table> style_footer(); } /* @@ -651,8 +650,59 @@ @ </form> @ <hr> @ Here is the default page footer: @ <blockquote><pre> @ %h(zDefaultFooter) + @ </pre></blockquote> + db_end_transaction(0); +} + +/* +** WEBPAGE: setup_ticket +*/ +void setup_ticket(void){ + const char *zConfig; + int isSubmit; + + login_check_credentials(); + if( !g.okSetup ){ + login_needed(); + } + isSubmit = P("submit")!=0; + db_begin_transaction(); + zConfig = P("cfg"); + if( zConfig==0 ){ + zConfig = db_text((char*)zDefaultTicketConfig, + "SELECT value FROM config WHERE name='ticket-configuration'"); + } + style_header("Edit Ticket Configuration"); + if( P("clear")!=0 ){ + db_multi_exec("DELETE FROM config WHERE name='ticket-configuration'"); + zConfig = zDefaultTicketConfig; + }else if( isSubmit ){ + char *zErr = ticket_config_check(zConfig); + if( zErr==0 ){ + db_multi_exec( + "REPLACE INTO config(name,value) VALUES('ticket-configuration'," + "%Q)", zConfig + ); + }else{ + @ <p><font color="red"><b> + @ SCRIPT ERROR: %h(zErr) + @ </b></font></p> + } + } + @ <form action="%s(g.zBaseURL)/setup_ticket" method="POST"> + @ <p>Edit the "subscript" script that defines the ticketing + @ system setup for this server.</p> + @ <textarea name="cfg" rows="40" cols="80">%h(zConfig)</textarea> + @ <br /> + @ <input type="submit" name="submit" value="Apply Changes"> + @ <input type="submit" name="clear" value="Revert To Default"> + @ </form> + @ <hr> + @ Here is the default page header: + @ <blockquote><pre> + @ %h(zDefaultTicketConfig) @ </pre></blockquote> db_end_transaction(0); }
Modified src/style.c from [ee998320c7] to [59e6a72711].
@@ -46,16 +46,20 @@ ** Add a new element to the submenu */ void style_submenu_element( const char *zLabel, const char *zTitle, - const char *zLink + const char *zLink, + ... ){ + va_list ap; assert( nSubmenu < sizeof(aSubmenu)/sizeof(aSubmenu[0]) ); aSubmenu[nSubmenu].zLabel = zLabel; aSubmenu[nSubmenu].zTitle = zTitle; - aSubmenu[nSubmenu].zLink = zLink; + va_start(ap, zLink); + aSubmenu[nSubmenu].zLink = vmprintf(zLink, ap); + va_end(ap); nSubmenu++; } /* ** Compare two submenu items for sorting purposes
Modified src/tkt.c from [73fae28608] to [1c6be6341e].
@@ -304,16 +304,22 @@ db_end_transaction(0); } /* ** WEBPAGE: tktview +** +** View a ticket. */ void tktview_page(void){ char *zScript; int nScript; login_check_credentials(); if( !g.okRdTkt ){ login_needed(); return; } + if( g.okWrTkt ){ + style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T", + g.zTop, PD("name","")); + } style_header("View Ticket"); ticket_init(); initializeVariablesFromDb(); zScript = (char*)SbS_Fetch(pInterp, "tktview_template", -1, &nScript); zScript = mprintf("%.*s", nScript, zScript); @@ -421,10 +427,18 @@ /* ** WEBPAGE: tktnew ** WEBPAGE: debug_tktnew +** +** Enter a new ticket. the tktnew_template script in the ticket +** configuration is used. The /tktnew page is the official ticket +** entry page. The /debug_tktnew page is used for debugging the +** tktnew_template in the ticket configuration. /debug_tktnew works +** just like /tktnew except that it does not really save the new ticket +** when you press submit - it just prints the ticket artifact at the +** top of the screen. */ void tktnew_page(void){ char *zScript; int nScript; char *zNewUuid = 0; @@ -447,15 +461,20 @@ } @ </form> style_footer(); } - - /* ** WEBPAGE: tktedit ** WEBPAGE: debug_tktedit +** +** Edit a ticket. The ticket is identified by the name CGI parameter. +** /tktedit is the official page. The /debug_tktedit page does the same +** thing except that it does not save the ticket change record when you +** press submit - it instead prints the ticket change record at the top +** of the page. The /debug_tktedit page is intended to be used when +** debugging ticket configurations. */ void tktedit_page(void){ char *zScript; int nScript; int nName; @@ -500,6 +519,63 @@ cgi_redirect(mprintf("%s/tktview/%s", g.zBaseURL, zName)); return; } @ </form> style_footer(); +} + +/* +** Check the ticket configuration in zConfig to see if it appears to +** be well-formed. If everything is OK, return NULL. If something is +** amiss, then return a pointer to a string (obtained from malloc) that +** describes the problem. +*/ +char *ticket_config_check(const char *zConfig){ + struct Subscript *p; + char *zErr = 0; + const char *z; + int n; + int i; + int rc; + sqlite3 *db; + static const char *azRequired[] = { + "tktnew_template", + "tktview_template", + "tktedit_template", + }; + + p = SbS_Create(); + rc = SbS_Eval(p, zConfig, strlen(zConfig)); + if( rc!=SBS_OK ){ + zErr = mprintf("%s", SbS_GetErrorMessage(p)); + SbS_Destroy(p); + return zErr; + } + for(i=0; i<sizeof(azRequired)/sizeof(azRequired[0]); i++){ + z = SbS_Fetch(p, azRequired[i], -1, &n); + if( z==0 ){ + zErr = mprintf("missing definition: %s", azRequired[i]); + SbS_Destroy(p); + return zErr; + } + } + z = SbS_Fetch(p, "ticket_sql", -1, &n); + if( z==0 ){ + zErr = mprintf("missing definition: ticket_sql"); + SbS_Destroy(p); + return zErr; + } + rc = sqlite3_open(":memory:", &db); + if( rc==SQLITE_OK ){ + char *zSql = mprintf("%.*s", n, z); + rc = sqlite3_exec(db, zSql, 0, 0, &zErr); + if( rc!=SQLITE_OK ){ + sqlite3_close(db); + SbS_Destroy(p); + return zErr; + } + /* TODO: verify that the TICKET table exists and has required fields */ + sqlite3_close(db); + } + SbS_Destroy(p); + return 0; }
Modified src/tktconfig.c from [64970a9836] to [c567cf64e8].
@@ -85,26 +85,19 @@ ** This configuration file just sets the values of various variables. ** Some of the variables have special meanings. The content of some ** of the variables are additional subscript scripts. */ -/* @-comment: # */ +/* @-comment: ** */ const char zDefaultTicketConfig[] = -@ ########################################################################## -@ # -@ # Every ticket configuration file should have a title. When you -@ # come up with a new ticket configuration, please change the title -@ # to something descriptive. -@ # -@ {Default Ticket Configuration} /ticket_config_title set -@ @ ############################################################################ -@ # Every ticket configuration *must* define a set of columns for the -@ # "ticket" table of the database. These column names will also be -@ # used as CGI parameter names, so to avoid problems it is best that -@ # the names be all lower-case alphabetic characters. The names must -@ # be unique and must not begin with "tkt_". +@ # Every ticket configuration *must* define an SQL statement that creates +@ # the TICKET table. This table must have three columns named +@ # tkt_id, tkt_uuid, and tkt_mtime. tkt_id must be the integer primary +@ # key and tkt_uuid and tkt_mtime must be unique. A configuration should +@ # define addition columns as necessary. All columns should be in all +@ # lower-case letters and should not begin with "tkt". @ # @ { @ CREATE TABLE ticket( @ -- Do not change any column that begins with tkt_ @ tkt_id INTEGER PRIMARY KEY,
Modified src/wiki.c from [06781e499d] to [9e63012182].
@@ -161,20 +161,20 @@ zBody = m.zWiki; } } } if( isSandbox || (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){ - style_submenu_element("Edit", "Edit Wiki Page", - mprintf("%s/wikiedit?name=%T", g.zTop, zPageName)); + style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T", + g.zTop, zPageName); } if( isSandbox || (rid && g.okApndWiki) ){ - style_submenu_element("Append", "Add A Comment", - mprintf("%s/wikiappend?name=%T", g.zTop, zPageName)); + style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T", + g.zTop, zPageName); } if( !isSandbox && g.okHistory ){ - style_submenu_element("History", "History", - mprintf("%s/whistory?name=%T", g.zTop, zPageName)); + style_submenu_element("History", "History", "%s/whistory?name=%T", + g.zTop, zPageName); } zHtmlPageName = mprintf("%h", zPageName); style_header(zHtmlPageName); blob_init(&wiki, zBody, -1); wiki_convert(&wiki, 0, 0);