(* Forum -- forum subapp Copyright (C) 2013 Benjamin Barenblat This file is a part of 6.947. 6.947 is is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 6.947 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with 6.947. If not, see . *) functor Make(Template : sig val generic : option string -> xbody -> page end) = struct open Styles open Author style entryList style entryMetadata style entryTitle style entryBody table entry : { Id : int, References : option int, Class : EntryClass.entryClass, Title : option string, Body : string, Author : author } PRIMARY KEY Id sequence entryIdS table vote : { QuestionId : int, Author : author, Value : Score.score } (* Grabs real name out of MIT certificate. *) val getName : transaction (option string) = getenv (blessEnvVar "SSL_CLIENT_S_DN_CN") (* Like query1', but automatically dereferences the field *) fun queryColumn [tab ::: Name] [field ::: Name] [state ::: Type] (q : sql_query [] [] [tab = [field = state]] []) (f : state -> state -> state) (initial : state) : transaction state = query q (fn row state => return (f row.tab.field state)) initial (* Sum all the votes on a single question. *) fun getScore (questionId : int) : transaction Score.score = queryColumn (SELECT Vote.Value FROM vote WHERE Vote.QuestionId = {[questionId]}) Score.update Score.undecided (***************************** Single questions ******************************) fun detail (id : int) : transaction page = authorOpt <- getName; question <- oneRow1 (SELECT * FROM entry WHERE Entry.Class = {[EntryClass.question]} AND Entry.Id = {[id]}); answerBlock <- queryX1 (SELECT * FROM entry WHERE Entry.Class = {[EntryClass.answer]} AND Entry.References = {[Some id]}) (fn answer =>

{[answer.Body]} —{[answer.Author]}

); return ( Template.generic (Some "Forum")

{[question.Title]}

{[question.Body]}

Asked by {[question.Author]}

{answerBlock}

Your answer