diff --git a/app/resources/results/Results.jl b/app/resources/results/Results.jl index d47e86c..dc38209 100644 --- a/app/resources/results/Results.jl +++ b/app/resources/results/Results.jl @@ -92,6 +92,11 @@ end function results(survey::SurveyID; cache::Bool=true, format::Symbol=:DataFrame) resids = responseids(survey; cache) + results(survey, resids; cache, format) +end + +function results(survey::SurveyID, resids::Vector{ResponseID}; + cache::Bool=true, format::Symbol=:DataFrame) res = response.(survey, resids; cache) qids = keys(questions(survey; cache)) data = Dict(q => map(r -> r[q].value, res) for q in qids) diff --git a/app/resources/results/ResultsController.jl b/app/resources/results/ResultsController.jl index 6aa2f05..3584d0d 100644 --- a/app/resources/results/ResultsController.jl +++ b/app/resources/results/ResultsController.jl @@ -33,6 +33,28 @@ function resultsfile(survey::SurveyID, format::AbstractString) end end +function resultsfile(survey::SurveyID, responseid::ResponseID, format::AbstractString) + @assert survey == Main.SurveysController.SURVEY.id + thesurvey = Main.SurveysController.SURVEY + response = Results.response(survey, responseid) + if format == "txt" + WebRenderable(sprint(show, thesurvey => response), :text) |> + Genie.Renderer.respond + elseif format == "org" + WebRenderable(sprint(show, MIME("text/org"), thesurvey => response), :text) |> + Genie.Renderer.respond + elseif format in ("csv", "tsv", "json") + WebRenderable(results(survey, [responseid], format=Symbol(format)), + if format == "json"; :json else :text end) |> + Genie.Renderer.respond + elseif format == "db" || format == "sqlite" + HTTP.Response(200, ["Content-Type" => "application/octet-stream"], + body = results(survey, [responseid], format=:sqlite)) + else + error("format $format not recognised") + end +end + function listsurveys() WebRenderable(sprint(JSON3.pretty, [Dict(:id => id, diff --git a/routes.jl b/routes.jl index dbbbbc3..44a4cc8 100755 --- a/routes.jl +++ b/routes.jl @@ -19,12 +19,33 @@ route("/submit-backpage", method=POST) do SurveysController.submit(postpayload(), backpage=true) end -route("/results(?:/(?:[A-Za-z0-9]+(?:\\.[a-z]+)?)?)?\$") do - survey, format = match(r"([A-Za-z0-9]+)?(?:\.([a-z]+))?$", currenturl()).captures - surveyid = tryparse(UInt32, survey, base=10) - if !isnothing(format) - ResultsController.resultsfile(surveyid, format) - else - ResultsController.resultsindex(surveyid) +route("/results/?") do; ResultsController.resultsindex() end + +route("/results/:survey#([A-Za-z0-9]+)", + named = :surveyindex) do + surveyid = tryparse(SurveysController.SurveyID, payload(:survey), base=10) + ResultsController.resultsindex(surveyid) +end + +route("/results/:survey#([A-Za-z0-9]+)\\.:format#([a-z]+)", + named = :surveyresult) do + surveyid = tryparse(SurveysController.SurveyID, payload(:survey), base=10) + ResultsController.resultsfile(surveyid, payload(:format)) +end + +route("/results/:survey#([A-Za-z0-9]+)/:responsefile#([A-Za-z0-9]+\\.[a-z]+)", + named = :result) do + surveyid = tryparse(SurveysController.SurveyID, payload(:survey), base=10) + response, format = split(payload(:responsefile), '.') + responseid = tryparse(SurveysController.ResponseID, response, + base=SurveysController.UID_ENCBASE) + try + ResultsController.resultsfile(surveyid, responseid, format) + catch e + if e isa MethodError || e isa AssertionError + Router.error(404, currenturl(), MIME"text/html") + else + rethrow(e) + end end end