Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 80 additions & 24 deletions modules/frus-ajax.xql
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
xquery version "3.0";
xquery version "3.1";

declare namespace output="http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace tei="http://www.tei-c.org/ns/1.0";
Expand All @@ -18,52 +18,108 @@ declare option output:media-type "application/json";
: This module is called from Javascript when the user wants to navigate to the next/previous
: page.
:)

(:~
: Look up the created and last modified dates of a resource, set the appropriate HTTP response headers,
: and, if appropriate, issue a 304 Not Modified status code.
:)
declare function local:set-headers($publication-id as xs:string, $document-id as xs:string, $section-id as xs:string?) {
let $created := pages:created($publication-id, $document-id, $section-id)
let $last-modified :=
pages:last-modified($publication-id, $document-id, $section-id)
(: For the purpose of comparing the resource's last modified date with the If-Modified-Since
: header supplied by the client, we must truncate any milliseconds from the last modified date.
: This is because HTTP-date is only specific to the second.
: @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1 :)
=> format-dateTime("[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01][Z]")
=> xs:dateTime()
let $if-modified-since := try { request:get-attribute("if-modified-since") => parse-ietf-date() } catch * { () }
let $should-return-304 :=
if (exists($last-modified) and exists($if-modified-since)) then
$if-modified-since ge $last-modified
else
()
return
(
app:set-created($created),
app:set-last-modified($last-modified),
if ($should-return-304) then
response:set-status-code(304)
else
()
)
};

let $url := request:get-parameter("url", ())
(: remove after beta. brittle url logic here. :)
let $url := if (starts-with($url, '/beta')) then substring-after($url, '/beta') else $url
let $toc := boolean(request:get-parameter("toc", ()))
let $match := analyze-string($url, "^/([^/]+)/([^/]+)/?(.*)$")
let $publication := $match//fn:group[@nr = "1"]/string()
let $volume := $match//fn:group[@nr = "2"]/string()
let $id := $match//fn:group[@nr = "3"]/string()
(: TODO Please add comments describing assumption of the path parsing and mapping onto publication-id/document-id/section-id logic :)
let $url-slug-1 := $match//fn:group[@nr = "1"]/string()
let $url-slug-2 := $match//fn:group[@nr = "2"]/string()
let $url-slug-3 := $match//fn:group[@nr = "3"]/string()

(: First, map the URL slugs onto the required parameters for looking up the requested XML source:
: publication-id, document-id, and section-id.
:
: For example:
:
: - /historicaldocuments/frus1969-76v18/d1 -> frus, frus1969-76v18, d1
: - /historicaldocuments/frus-history/chapter-2 -> frus-history-monograph, frus-history-monograph, chapter-2
: - /departmenthistory/buildings/intro -> buildings, buildings, intro
: - /about/hac/August-2021 -> hac, hac, August-2021
:)

let $section-id := $url-slug-3
let $document-id :=
if ($url-slug-2) then
$url-slug-2
else
$url-slug-1
let $publication-id :=
switch ($publication)
switch ($url-slug-1)
case 'historicaldocuments' return
switch ($volume)
switch ($document-id)
case "frus-history" return "frus-history-monograph"
default return 'frus'
case 'about' return $volume
case 'about' return $document-id
case 'departmenthistory' return
switch ($volume)
switch ($document-id)
case 'buildings' return 'buildings'
case 'short-history' return 'short-history'
case 'timeline' return 'timeline'
default return $publication
default return $publication
let $log := console:log("publication: " || $publication || ", volume: " || $volume)
let $volume := if ($volume) then $volume else $publication-id (: TODO see above - please explain :)
let $xml := pages:load-xml($publication-id, $volume, $id, "div")
default return $url-slug-1
default return $url-slug-1

(: Load XML and generate assets :)

let $xml := pages:load-xml($publication-id, $document-id, $section-id, "div")
return
if ($xml) then
(

(: Set HTTP Headers - and cut the request short with a 304 status code if possible :)

local:set-headers($publication-id, $document-id, $section-id),

(: ... then generate the assets :)

let $odd := if ($publication-id) then map:get($config:PUBLICATIONS, $publication-id)?transform else $config:odd-transform-default
let $prev := pages:get-previous($xml)
let $next := pages:get-next($xml)
let $base-path :=
if (map:contains(map:get($config:PUBLICATIONS, $publication-id), 'base-path')) then
map:get($config:PUBLICATIONS, $publication-id)?base-path($volume, $id)
map:get($config:PUBLICATIONS, $publication-id)?base-path($document-id, $section-id)
else ()
let $html :=
if ($xml instance of element(tei:pb)) then
let $href := concat('//', $config:S3_DOMAIN, '/frus/', substring-before(util:document-name($xml), '.xml') (:ACK why is this returning blank?!?! root($xml)/tei:TEI/@xml:id:), '/medium/', $xml/@facs, '.png')
let $href := concat('//', $config:S3_DOMAIN, '/frus/', $document-id, '/medium/', $xml/@facs, '.png')
return
<div class="content">
<img src="{$href}" class="img-responsive img-thumbnail center-block"/>
</div>
else
pages:process-content($odd, pages:get-content($xml), map { "base-uri": $base-path })
let $html := app:fix-links($html)
let $doc := replace($volume, "^.*/([^/]+)$", "$1")
let $doc := replace($document-id, "^.*/([^/]+)$", "$1")
let $model := map {
"odd": $odd,
"data": $xml
Expand All @@ -74,20 +130,20 @@ return
else
pages:deep-section-breadcrumbs(<n/>, $model, true())
let $mediaLink :=
if (fh:media-exists($volume, $id, ".pdf")) then
fh:pdf-url($volume, $id)
if (fh:media-exists($document-id, $section-id, ".pdf")) then
fh:pdf-url($document-id, $section-id)
else
()
let $head :=
if ($id) then
if ($section-id) then
if ($xml instance of element(tei:div)) then
$xml/tei:head[1] ! functx:remove-elements-deep(., 'note')
else
root($xml)//tei:teiHeader/tei:fileDesc/tei:titleStmt/tei:title[@type = 'complete']
(: we can't trust pages:load-xml for the purposes of finding a document's title, since it returns the document's first descendant div :)
(: allow for pages that don't have $config:PUBLICATIONS?select-document defined :)
else if ($publication-id and map:contains(map:get($config:PUBLICATIONS, $publication-id), 'select-document')) then
map:get($config:PUBLICATIONS, $publication-id)?select-document($volume)//tei:teiHeader/tei:fileDesc/tei:titleStmt/tei:title[@type = 'complete']
map:get($config:PUBLICATIONS, $publication-id)?select-document($document-id)//tei:teiHeader/tei:fileDesc/tei:titleStmt/tei:title[@type = 'complete']
(: allow for pages that don't have an entry in $config:PUBLICATIONS at all :)
else
()
Expand Down Expand Up @@ -116,7 +172,6 @@ return
"windowTitle": normalize-space(string-join(($head, $doc-title, $publication-title, "Office of the Historian")[. ne ''], " - ")),
"toc": if ($toc) then toc:toc($model, $xml, true(), true()) else (),
"tocCurrent": $xml/ancestor-or-self::tei:div[@type != "document"][1]/@xml:id/string(),
(: "breadcrumbSection": fh:breadcrumb-heading($model, $xml), :)
"breadcrumbSection": $breadcrumbs,
"persons":
let $persons :=
Expand All @@ -142,5 +197,6 @@ return
</output:serialization-parameters>
)
}
)
else
map { "error": "Not found" }