From 612b0e754176f1b7098c5c1d7973028a22ee902d Mon Sep 17 00:00:00 2001 From: Mika Havela Date: Tue, 15 Apr 2008 12:52:00 +0000 Subject: Creating a acf-gnats so that users can view/add bugreports to bugs@alpinelinux.org git-svn-id: svn://svn.alpinelinux.org/acf/gnats/trunk@985 ab2d0c66-481e-0410-8bed-d214d4d58bed --- gnats-controller.lua | 515 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 515 insertions(+) create mode 100644 gnats-controller.lua (limited to 'gnats-controller.lua') diff --git a/gnats-controller.lua b/gnats-controller.lua new file mode 100644 index 0000000..4fa036c --- /dev/null +++ b/gnats-controller.lua @@ -0,0 +1,515 @@ +module(..., package.seeall) + +-- Load libraries +require("format") + +-- Set variables +local newrecordtxt = "[New]" +local anytxt = "Any" +local bugreportreceiver = "bugs@alpinelinux.org" + +local descr = { + labels = { + ['category'] = "Category", + ['severity'] = "Severity", + ['priority'] = "Priority", + ['class'] = "Class", + ['state'] = "State", + ['skipclosed'] = "Skip/Hide closed", + ['text'] = "Text in single-line fields", + ['multitext'] = "Text in multi-line fields", + ['responsible'] = "Responsible", + ['originator'] = "Originator", + ['release'] = "Alpine release", + ['environment']="Environment", + ['description']="Description", + ['howtorepeat']="How-to-repeat this bug", + ['fix']="Fix", + ['synopsis']="Short description (on line)", + ['from']="Your e-mail address", + ['reporter_name']="Your full name", + ['reporter_id']="Your ID (Submitter ID)", + ['reporter_org']="Your organization name", + + header = { + ['received'] = "Received", + ['to'] = "To", + ['from'] = "From", + ['date'] = "Date", + ['message_id'] = "Message ID", + ['subject'] = "Subject", + ['return_path'] = "Return path", + }, + sfields = { + ['number'] = "Number", + ['class'] = "Class", + ['responsible'] = "Responsible", + ['category'] = "Category", + ['priority'] = "Priority", + ['confidential'] = "Confidential", + ['originator'] = "Originator", + ['severity'] = "Severity", + ['keywords'] = "Keywords", + ['arrival_date'] = "Arrival date", + ['quarter'] = "Quarter", + ['synopsis'] = "Synopsis", + ['notify_list'] = "Notify list", + ['submitter_id'] = "Submitter id", + ['date_required'] = "Date required", + ['release'] = "Release", + ['last_modified'] = "Last modified", + ['closed_date'] = "Closed date", + ['state'] = "State", + }, + mfields = { + ['environment'] = "Environment", + ['release_note'] = "Release note", + ['audit_trail'] = "Audit trail", + ['howtorepeat'] = "How to repeat", + ['organization'] = "Organization", + ['fix'] = "Fix", + ['unformatted'] = "Unformatted", + }, + }, + audit_trail = { + ['Responsible-Changed-From-To'] = "Responsible Changed", + ['State-Changed-From-To'] = "State Changed", + ['From'] = "Reply via E-mail", + }, + maildescriptions = { + ['from'] = "From: ", + ['reporter_id'] = ">Submitter-Id: ", + ['xxx'] = ">Notify-List: ", + ['originator'] = ">Originator: ", + ['reporter_org'] = ">Organization: ", + ['synopsis'] = ">Synopsis: ", + ['xxx'] = ">Confidential: ", + ['severity'] = ">Severity: ", + ['priority'] = ">Priority: ", + ['category'] = ">Category: ", + ['class'] = ">Class: ", + ['release'] = ">Release: ", + ['environment'] = ">Environment: ", + ['description'] = ">Description: ", + ['howtorepeat'] = ">How-To-Repeat:", + ['fix'] = ">Fix: ", + }, + + } + +-- ################################################################################ +-- LOCAL FUNCTIONS + +local function list_redir(self) + self.conf.action = "status" + self.conf.type = "redir" + error (self.conf) +end + + +-- ################################################################################ +-- PUBLIC FUNCTIONS +mvc = {} +function mvc.on_load(self, parent) + if (self.worker[self.conf.action] == nil ) or ( self.conf.action == "init" ) then + self.worker[self.conf.action] = list_redir(self) + end +end + +function status(self) + return { status=self.model.getstatus() } +end + +function expert(self) + local modifications = self.clientdata.filecontent or "" + if ( self.clientdata.cmdsave ) then + modifications = self.model:update_filecontent(modifications) + end + local url = ENV["SCRIPT_NAME"] .. self.conf.prefix .. self.conf.controller + + local status=self.model.getstatus() + local filedetailsresult, file = self.model:get_filedetails() + + -- Add buttons + file.cmdsave = cfe ({ + name="cmdsave", + label="Apply settings", + value="Apply", + type="submit", + }) + if (self.clientdata.cmdsave) then + file.cmdsave.descr="* Changes has been saved!" + end + + return ( { + option={ script=ENV["SCRIPT_NAME"], + prefix=self.conf.prefix, + controller = self.conf.controller, + action = "update", + extra = "" }, + status = status, + file = file, + modifications = modifications, + url = url, } ) +end + +function edit(self) + + -- Save changes + local modifications = self.clientdata.filecontent or "" + if ( self.clientdata.cmdsave ) then + modifications = self.model:update_filecontent(modifications,self.clientdata.name) + end + + local status = self.model:getstatus(self) + local filedetailsresult, file = self.model:get_filedetails(self.clientdata.name) + + + if not (filedetailsresult) then + self.conf.action = "status" + self.conf.type = "redir" + error (self.conf) + end + + -- Add a cmd button to the view + file.cmdsave = cfe({ name="cmdsave", + label="Save/Apply above settings", + value="Save", + type="submit", + }) + if (modifications) then + file.cmdsave.descr="* Changes has been saved!" + end + + return { + option={ script=ENV["SCRIPT_NAME"], + prefix=self.conf.prefix, + controller = self.conf.controller, + action = "edit", + extra = "", + }, + modifications = modifications, + file = file, + status = status, + startstop = startstop, + } +end + +function query(self) + local query = {} + + query.pr = cfe({ + name="pr", + label="Query a specific PR number:", + }) + query.pr_cmd = cfe({ + name="pr_cmd", + label="Submit the query", + type="submit", + value="Submit", + }) + + local tags = { "category", "severity", "priority", "class", "state", } + for k,val in pairs(tags) do + query[val] = cfe({ + name=val, + label=(descr.labels[val] or val), + value=anytxt, + type="select", + option=self.model:get_select_opt(val), + }) + table.insert(query[val].option, 1, anytxt) + -- If there is only a limited amount records, then present as radio buttons. + if (#query[val].option < 6) then query[val].type="radio" end + end + + local val = "responsible" + query[val] = cfe({ + name=val, + label=(descr.labels[val] or val), + value=anytxt, + type="select", + option=self.model:list_responsible(), + }) + table.insert(query[val].option, 1, anytxt) + + local tags = { "skipclosed", "text", "multitext", } + for k,val in pairs(tags) do + query[val] = cfe({ + name=val, + label=(descr.labels[val] or val), + option=self.model:get_select_opt(val), + }) + end + + -- Show 'skipclosed' as a checkbox instead + query.skipclosed.type="checkbox" + query.skipclosed.checked="Yes" + + query.advanced_cmd = cfe({ + name="advanced_cmd", + label="Submit the advanced query", + type="submit", + value="Submit", + }) + + return { + option={ script=ENV["SCRIPT_NAME"], + prefix=self.conf.prefix, + controller = self.conf.controller, + action = "edit", + extra = "", + }, + query = query, + } +end + +function queryresult(self) + local query = {} + local pr_id = self.clientdata.pr + if (tonumber(pr_id)) then + query.header, query.sfields, query.mfields = self.model:read_pr(pr_id) + else + list_redir(self) + end + + local myform = query.header + for k,v in pairs(myform) do + myform[k] = cfe({ + name=k, + label=descr.labels.header[k] or k, + value=string.gsub(myform[k], "\"", ""), + }) + end + + local myform = query.sfields + for k,v in pairs(myform) do + myform[k] = cfe({ + name=k, + label=descr.labels.sfields[k] or k, + value=string.gsub(myform[k], "\"", ""), + }) + end + + local myform = query.mfields + for k,v in pairs(myform) do + myform[k] = cfe({ + name=k, + label=descr.labels.mfields[k] or k, + value=string.gsub(myform[k], "\"", ""), + }) + end + + local audit_trail_table = {} + local checkstring = "" + local checkstring2 = 0 + table.insert(audit_trail_table, cfe({class="", label=""})) + + for k,v in pairs(format.string_to_table(query.mfields.audit_trail.value, "\n")) do + if (v == "") then + checkstring2 = checkstring2 + 1 + end + if (checkstring2 == 99) then + table.insert(audit_trail_table, cfe({class="Unknown", label=""})) + checkstring = "" + checkstring2 = 0 + end + for k1, v1 in pairs(descr.audit_trail) do + if (string.match(v, "^".. string.gsub(k1, "-", "%%-"))) then + table.insert(audit_trail_table, cfe({class=k1, label=v1})) + checkstring = k1 + checkstring2 = 0 + break + end + end + if (#audit_trail_table > 0) then + table.insert(audit_trail_table[#audit_trail_table], string.match(v, "^.+")) --Strips empty lines + end + end + + query.mfields.audit_trail.option=audit_trail_table + + return { + option={ script=ENV["SCRIPT_NAME"], + prefix=self.conf.prefix, + controller = self.conf.controller, + action = "edit", + extra = "", + }, + query = query, + } + +end + +function summary(self) + -- parse the search criterias - select boxes + local action = "Query" + local s = {} + for i, f in ipairs({"class", "category", "severity", "priority", "state", "responsible"}) do + s[f] = self.model:validate_field(self.clientdata[f], f) + end + + local invalid = nil + -- parse the search criterias - input boxes + for i,f in ipairs({"text", "multitext", "originator"}) do + s[f] = self.model:validate_textfield(self.clientdata[f], f) + -- replace this with ajax stuff? + if action == "Query" and s[f] == nil then + self.model:set_invalid_field(f) + invalid = true + end + -- if field is blank, then ignore it + if action == "Query" and s[f] == "" then + s[f] = nil + end + end + + -- we have found atleast one invalid field. reset the action + if invalid then + action = nil + end + + if (self.clientdata.skipclosed) then + s["skip-closed"] = "" + else + s["skip-closed"] = nil + end + + -- Set the search criterias + self.model:set_search_criteria(s) + + return { + option={ script=ENV["SCRIPT_NAME"], + prefix=self.conf.prefix, + controller = self.conf.controller, + action = "edit", + extra = "", + }, + summary = self.model:summary(), + } +end + +function report(self) + local reportform = {} + local status = self.model:getstatus(self) + + local alltags = { "reporter_name", "from", "reporter_id", "reporter_org", + "synopsis","severity","priority","category","class","release","environment", + "description", "howtorepeat", "fix", } + + + for k,val in pairs(alltags) do + reportform[val] = cfe({ + name=val, + label=(descr.labels[val] or val), + value=(self.clientdata[val] or ""), + }) + end + + local tags = { "category", "priority","severity","class" } + for k,val in pairs(tags) do + reportform[val] = cfe({ + name=val, + label=(descr.labels[val] or val), + value=(self.clientdata[val] or ""), + type="select", + option=self.model:get_select_opt(val), + }) + -- If there is only a limited amount records, then present as radio buttons. + if (#reportform[val].option < 6) then + reportform[val].type="radio" + else + table.insert(reportform[val].option, 1, "") + end + end + + reportform.description.type="longtext" + reportform.howtorepeat.type="longtext" + reportform.fix.type="longtext" + reportform.environment.type="longtext" + reportform.release.value=status.alpinerelease.value or "" + + -- Add buttons + reportform.submit = cfe ({ + name="submit", + label="Submit this repport", + value="Submit", + type="submit", + }) + + if (self.clientdata.submit) then + + if not (self.clientdata.from) or (#self.clientdata.from == 0) then + reportform.from.errtxt = "You need to enter a valid e-mail address" + end + + if not (self.clientdata.synopsis) or (#self.clientdata.synopsis == 0) then + reportform.synopsis.errtxt = "You need to enter a valid online-description" + end + + if not (self.clientdata.severity) or (#self.clientdata.severity == 0) then + reportform.severity.errtxt = "You need to choose one of these options" + end + + if not (self.clientdata.priority) or (#self.clientdata.priority == 0) then + reportform.priority.errtxt = "You need to choose one of these options" + end + + if not (self.clientdata.category) or (#self.clientdata.category == 0) then + reportform.category.errtxt = "You need to choose one of these options" + end + + if not (self.clientdata.class) or (#self.clientdata.class == 0) then + reportform.class.errtxt = "You need to choose one of these options" + end + + local noerrorsexists + for k,v in pairs(alltags) do + noerrorsexists = false + if (#reportform[v]['errtxt'] > 0) then break end + noerrorsexists = true + end + + -- If we had no errors, then we proceed with creating/sending the bugreport + if (noerrorsexists) then + local bugreport = {} + table.insert(bugreport, "To: " .. (bugreportreceiver or "")) + table.insert(bugreport, "From: " .. (self.clientdata.from or "")) + table.insert(bugreport, "Reply-To: " .. (self.clientdata.from or "")) + table.insert(bugreport, "") + for k,v in pairs({"reporter_id", "notify_list", "originator", "synopsis", "confidential", "severity", + "priority", "category", "class", "release", }) do + if (v) and (descr.maildescriptions[v]) and (self.clientdata[v]) then + table.insert(bugreport, descr.maildescriptions[v] .. self.clientdata[v] ) + end + end + table.insert(bugreport, descr.maildescriptions.environment .. "\n" .. (self.clientdata.environment or "") .."\n" ) + table.insert(bugreport, descr.maildescriptions.howtorepeat .. "\n" .. (self.clientdata.howtorepeat or "") .."\n" ) + + table.insert(bugreport, descr.maildescriptions.fix .. "\n" .. (self.clientdata.fix or "") .."\n" ) + + local bugreportsuccess, bugreport = self.model:sendbug(bugreport) + + if (bugreportsuccess) then + self.conf.action = "reportsuccess" + self.conf.type = "redir" + error (self.conf) + end + reportform.submit.errtxt = "Something went wrong because the report could not be sent.\n" .. bugreport + end + end + + return { + option={ script=ENV["SCRIPT_NAME"], + prefix=self.conf.prefix, + controller = self.conf.controller, + action = "edit", + extra = "", + }, + reportform = reportform, + } +end + +function reportsuccess() + -- Just show that the report was successfully sent. +end -- cgit v1.2.3