Skip to content
Merged
Show file tree
Hide file tree
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
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@
Please see https://github.com/purescript/pursuit/blob/master/CHANGELOG.md for
the most up-to-date version of this file.

## v0.9.14

- Fix the version selector getting stuck on "Loading …" after a restart
(@thomashoneyman)

The version dropdown on package pages was initialized by a per-page inline
script that Yesod bundles into a dynamic `/static/widget/<hash>.js` file,
whose contents live only in the running backend's in-memory store. Any
backend restart (such as a deploy) orphaned those widgets: nginx kept
serving already-cached HTML that referenced them, the script 404'd, and the
selector never populated. The version selector, search box, and search
"load more" link are now initialized from the statically embedded
`Pursuit.js`, which is served from disk and survives restarts.

## v0.9.13

- Avoid decoding the latest package version just to render deprecation badges
Expand Down
2 changes: 0 additions & 2 deletions src/Handler/Packages.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
module Handler.Packages where

import Import
import Text.Julius (rawJS)
import Text.Blaze (ToMarkup, toMarkup)
import qualified Data.Char as Char
import Data.Version
Expand Down Expand Up @@ -301,7 +300,6 @@ defaultLayout404 widget =

versionSelector :: PackageName -> Version -> WidgetFor App ()
versionSelector pkgName version = do
versionSelectorIdent <- newIdent
let route = PackageAvailableVersionsR (PathPackageName pkgName)
availableVersionsUrl <- getUrlRender <*> pure route
$(widgetFile "versionSelector")
Expand Down
52 changes: 43 additions & 9 deletions static/js/Pursuit.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
(function() {
/* Expects arguments as an Object with the following properties:
* - currentVersion (String):
/* Expects the version selector <select> element, which carries its per-page
* configuration in data attributes:
* - data-current-version (String):
* the version of docs that is being shown on this page.
* - elementId (String):
* the HTML id of the version selector element.
* - availableVersionsUrl (String):
* - data-available-versions-url (String):
* The URL to fetch the available versions for this package from.
*
* This initializer is invoked from this (statically served) script rather than
* from an inline per-page script, so that it keeps working across backend
* restarts. Inline widget scripts are served from the backend's in-memory
* EmbeddedStatic store and are orphaned when it restarts, which would leave
* already-cached pages stuck showing "Loading …".
*/
function initializeVersionSelector(args) {
function initializeVersionSelector(selector) {
var currentVersion = selector.getAttribute('data-current-version')
var availableVersionsUrl = selector.getAttribute('data-available-versions-url')

function getJSON(url, callback) {
var req = new XMLHttpRequest()
req.open('GET', url, true)
Expand All @@ -30,7 +38,7 @@ function initializeVersionSelector(args) {
el.setAttribute("value", url)

// Set the 'selected' attribute on the current version
if (version === args.currentVersion) {
if (version === currentVersion) {
el.setAttribute('selected', null)
}

Expand All @@ -52,13 +60,12 @@ function initializeVersionSelector(args) {

// Set an onchange handler so that selecting a version in the <select>
// will navigate to the new page
var selector = document.getElementById(args.elementId)
selector.onchange = function() {
window.location.href = this.value
}

// Load the <option> elements via AJAX
getJSON(args.availableVersionsUrl, function(data) {
getJSON(availableVersionsUrl, function(data) {
// Delete the placeholder <option>
selector.removeChild(selector.firstChild)

Expand Down Expand Up @@ -173,4 +180,31 @@ window.Pursuit = {
initializeSearchForm: initializeSearchForm,
initializeLoadMoreLink: initializeLoadMoreLink
}

// Wire everything up on page load. This script is served statically (embedded
// at compile time), so it is always available; doing initialization here rather
// than from inline per-page scripts means the page's dynamic behaviour survives
// backend restarts. This script is loaded in <head>, so wait for the DOM.
function onReady(fn) {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', fn)
} else {
fn()
}
}

onReady(function() {
if (document.getElementById('search-input')) {
initializeSearchForm()
}

var selectors = document.querySelectorAll('.version-selector')
for (var i = 0; i < selectors.length; i++) {
initializeVersionSelector(selectors[i])
}

if (document.getElementById('load-more-link')) {
initializeLoadMoreLink()
}
})
})()
1 change: 0 additions & 1 deletion templates/default-layout.julius

This file was deleted.

1 change: 0 additions & 1 deletion templates/search.julius

This file was deleted.

2 changes: 1 addition & 1 deletion templates/versionSelector.hamlet
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<select id=#{versionSelectorIdent} .version-selector>
<select .version-selector data-current-version=#{showVersion version} data-available-versions-url=#{availableVersionsUrl}>
<option id="placeholder" disabled="disabled">
Loading …
5 changes: 0 additions & 5 deletions templates/versionSelector.julius

This file was deleted.

Loading