FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Revert "Revert "Merge branch 'oja-offline-xwords'"" · devhttps/frontend@10bc6d0 · GitHub

Revert "Revert "Merge branch 'oja-offline-xwords'"" · devhttps/frontend@10bc6d0 · GitHub
Skip to content

Navigation Menu

Commit 10bc6d0

Browse files
committed
Revert "Revert "Merge branch 'oja-offline-xwords'""
This reverts commit 0a233ef.
1 parent 7d38131 commit 10bc6d0

25 files changed

Lines changed: 352 additions & 88 deletions

File tree

‎.gitignore‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ static/hash
6161
static/requirejs
6262
static/target
6363

64-
static/src/systemjs-bundle-config.js
6564
static/src/stylesheets/icons/*
6665

6766
# Eclipse #

‎Gruntfile.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module.exports = function (grunt) {
1010
isDev: (grunt.option('dev') !== undefined) ? Boolean(grunt.option('dev')) : process.env.GRUNT_ISDEV === '1',
1111
singleRun: grunt.option('single-run') !== false,
1212
staticTargetDir: './static/target/',
13+
staticSrcDir: './static/src/',
1314
staticHashDir: './static/hash/',
1415
testConfDir: './static/test/javascripts/conf/',
1516
requirejsDir: './static/requirejs',
@@ -111,7 +112,7 @@ module.exports = function (grunt) {
111112
grunt.registerTask('compile:fonts', ['mkdir:fontsTarget', 'webfontjson']);
112113
grunt.registerTask('compile:flash', ['copy:flash']);
113114
grunt.registerTask('compile:inlineSvgs', ['copy:inlineSVGs', 'svgmin:inlineSVGs']);
114-
grunt.registerTask('compile:conf', ['copy:headJs', 'copy:inlineCss', 'copy:assetMap', 'compile:inlineSvgs', 'uglify:conf']);
115+
grunt.registerTask('compile:conf', ['copy:headJs', 'copy:inlineCss', 'copy:assetMaps', 'compile:inlineSvgs', 'uglify:conf']);
115116
grunt.registerTask('compile', [
116117
'compile:css',
117118
'compile:js',

‎admin/app/views/admin_main.scala.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777
<link href='//fonts.googleapis.com/css?family=Open+Sans:800' rel='stylesheet' type='text/css'>
7878

7979
<script>
80-
@Html(Static.js.systemJsSetupFragment)
80+
@Html(Static.systemJs.setupFragment)
8181

8282
// Our app assumes a normal env
8383
window.guardian = {
Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,59 @@
11
package controllers
22

3-
import common.ExecutionContexts
4-
import model.Cached
5-
import play.api.mvc.{Action, Controller}
3+
import model.{MetaData, Cached}
4+
import com.gu.contentapi.client.model.Crossword
5+
import common.{Logging, Edition, ExecutionContexts}
6+
import conf.LiveContentApi
7+
import crosswords.CrosswordData
8+
import play.api.mvc.{RequestHeader, Result, Action, Controller}
69

7-
object WebAppController extends Controller with ExecutionContexts {
10+
import scala.concurrent.Future
11+
12+
class OfflinePage(val crossword: CrosswordData) extends MetaData {
13+
lazy val id: String = "offline-page"
14+
lazy val section: String = ""
15+
lazy val analyticsName: String = id
16+
lazy val webTitle: String = "Unable to connect to the Internet"
17+
}
18+
19+
object WebAppController extends Controller with ExecutionContexts with Logging {
820

921
def serviceWorker() = Action { implicit request =>
1022
Cached(3600) {
11-
conf.Switches.NotificationsSwitch.isSwitchedOn match {
12-
case true => Ok(templates.js.serviceWorker())
13-
case false => NotFound
23+
if (conf.Switches.NotificationsSwitch.isSwitchedOn || conf.Switches.OfflinePageSwitch.isSwitchedOn) {
24+
Ok(templates.js.serviceWorker())
25+
} else {
26+
NotFound
1427
}
1528
}
1629
}
1730

1831
def manifest() = Action {
1932
Cached(3600) { Ok(templates.js.webAppManifest()) }
2033
}
34+
35+
36+
protected def withCrossword(crosswordType: String, id: Int)(f: (Crossword) => Result)(implicit request: RequestHeader): Future[Result] = {
37+
LiveContentApi.getResponse(LiveContentApi.item(s"crosswords/series/quick", Edition(request)).showFields("all")).map { response =>
38+
val maybeCrossword = for {
39+
content <- response.results.headOption
40+
crossword <- content.crossword }
41+
yield f(crossword)
42+
maybeCrossword getOrElse InternalServerError("Crossword response from Content API invalid.")
43+
} recover { case e =>
44+
log.error("Content API query returned an error.", e)
45+
InternalServerError("Content API query returned an error.")
46+
}
47+
}
48+
49+
def offlinePage() = Action.async { implicit request =>
50+
if (conf.Switches.OfflinePageSwitch.isSwitchedOn) {
51+
withCrossword("quick", 14127) { crossword =>
52+
Cached(60)(Ok(views.html.offlinePage(
53+
new OfflinePage(CrosswordData.fromCrossword(crossword)))))
54+
}
55+
} else {
56+
Future(NotFound)
57+
}
58+
}
2159
}

‎applications/app/templates/serviceWorker.scala.js‎

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,74 @@
55
/*global self*/
66
/*global clients*/
77

8+
//
9+
// Offline page
10+
//
11+
12+
var staticCacheName = 'static';
13+
14+
var getISODate = function () { return new Date().toISOString().split('T')[0]; };
15+
16+
var updateCache = function () {
17+
return caches.open([getISODate(), staticCacheName].join('-')).then(function (cache) {
18+
return cache.addAll([
19+
'/offline-page',
20+
'@Static("stylesheets/head.content.css")',
21+
'@Static("stylesheets/content.css")',
22+
'@Static("stylesheets/print.css")',
23+
// Crossword pages use jspm
24+
'@StaticJspm("javascripts/core.js")',
25+
'@StaticJspm("javascripts/bootstraps/app.js")',
26+
'@StaticJspm("javascripts/es6/bootstraps/crosswords.js")'
27+
]);
28+
});
29+
};
30+
31+
var deleteOldCaches = function () {
32+
return caches.keys().then(function (keys) {
33+
return Promise.all(
34+
keys.map(function (key) {
35+
if (!keyMatchesTodaysCache(key)) {
36+
return caches.delete(key);
37+
}
38+
})
39+
);
40+
})
41+
};
42+
43+
var keyMatchesTodaysCache = function (key) {
44+
return new RegExp('^' + getISODate() + '-').test(key);
45+
};
46+
47+
self.addEventListener('install', function (event) {
48+
event.waitUntil(updateCache());
49+
});
50+
51+
this.addEventListener('fetch', function (event) {
52+
caches.keys().then(function (keys) {
53+
var isUpdated = keys.some(keyMatchesTodaysCache);
54+
55+
if (!isUpdated) {
56+
updateCache().then(deleteOldCaches);
57+
}
58+
});
59+
60+
event.respondWith(
61+
fetch(event.request)
62+
.catch(function () {
63+
// If a request is cached, respond with that. Otherwise respond
64+
// with the shell, whose subresources will be in the cache.
65+
return caches.match(event.request).then(function (response) {
66+
return response || caches.match('/offline-page');
67+
})
68+
})
69+
);
70+
});
71+
72+
//
73+
// Push notifications
74+
//
75+
876
var findInArray = function (array, fn) {
977
for (var i = array.length - 1; i >= 0; i--) {
1078
var value = array[i];
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
@(offlinePage: controllers.OfflinePage)(implicit request: RequestHeader)
2+
3+
@import play.api.libs.json._
4+
5+
<!DOCTYPE html>
6+
<html id="js-context" class="js-off is-not-modern id--signed-out" data-page-path="@request.path">
7+
8+
<head>
9+
<meta charset="utf-8" />
10+
<title>@views.support.Title(offlinePage)</title>
11+
12+
@fragments.metaData(offlinePage)
13+
14+
@* get the stylesheets downloading ASAP *@
15+
@fragments.stylesheetLinks(None)
16+
17+
@* polyfill, feature detect etc before we try and use the stylesheets *@
18+
@fragments.javaScriptPreFlight(offlinePage)
19+
20+
@* try and load fonts before we use the stylesheets *@
21+
@fragments.fonts()
22+
23+
@* start trying to use the stylesheets *@
24+
@fragments.stylesheetLinksEnable()
25+
26+
<script>
27+
@Html(Static.systemJs.setupFragment)
28+
29+
@* Service worker only caches the bundles, so the offline page can only ask for those.
30+
For production, we rely on bundles from systemJsSetup *@
31+
@if(play.Play.isDev()) {
32+
System.config({ bundles: @Html(Static.systemJs.bundleConfig) });
33+
}
34+
35+
@Html(templates.headerInlineJS.js.bootSystemJS(offlinePage).body)
36+
</script>
37+
</head>
38+
<body
39+
id="top"
40+
itemscope itemtype="http://schema.org/WebPage">
41+
42+
<a class="u-h skip" href="#maincontent" data-link-name="skip : main content">Skip to main content</a>
43+
44+
@fragments.header(offlinePage)
45+
46+
<div class="l-side-margins">
47+
<article id="crossword" class="content content--article tonal tonal--tone-news" role="main">
48+
<div class="content__head tonal__head tonal__head--tone-news">
49+
<div class="gs-container">
50+
<div class="content__main-column content__main-column--single-column">
51+
<h1 class="content__headline">Unable to connect to the Internet</h1>
52+
<p>In the meantime, how about a quick crossword?</p>
53+
<button class="button js-open-crossword-btn">Open crossword</button>
54+
</div>
55+
<div class="js-crossword-container is-hidden u-baseline-top">
56+
<h2><a href="/crosswords/@offlinePage.crossword.id">@offlinePage.crossword.name</a></h2>
57+
<div class="js-crossword"
58+
data-crossword-data="@Json.stringify(Json.toJson(offlinePage.crossword))">
59+
</div>
60+
</div>
61+
</div>
62+
</div>
63+
</article>
64+
</div>
65+
66+
@fragments.footer(offlinePage)
67+
68+
@fragments.footerJavaScript()
69+
70+
</body>
71+
</html>

‎applications/app/views/videoEmbed.scala.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
@bootSystemJs() = {
3131
<script>
32-
@Html(Static.js.systemJsSetupFragment)
32+
@Html(Static.systemJs.setupFragment)
3333

3434
// Bracket notation for IE8 (import is reserved)
3535
System['import']('core').then(function () {

‎applications/conf/routes‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ GET /crosswords/optin
3333
GET /crosswords/optout controllers.CrosswordPreferencesController.crosswordsOptOut
3434

3535
# Web App paths
36-
GET /2015-05-28-2-service-worker.js controllers.WebAppController.serviceWorker()
36+
GET /offline-page controllers.WebAppController.offlinePage()
37+
GET /service-worker.js controllers.WebAppController.serviceWorker()
3738
GET /2015-06-24-manifest.json controllers.WebAppController.manifest()
3839

3940
GET /$path<.+/\d\d\d\d/\w\w\w/\d\d> controllers.AllIndexController.on(path)

‎bundle.js‎

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,21 +85,43 @@ var writeBundlesToDisk = function (bundles) {
8585
});
8686
};
8787

88+
var createModuleExpressionToFilenameMap = function (bundles) {
89+
return Promise.all(bundles.map(function (bundle) {
90+
return System.normalize(bundle.id).then(function (absolutePath) {
91+
absolutePath = absolutePath.replace('file://', '');
92+
var pathRelativeToDir = path.relative(__dirname, absolutePath);
93+
return path.relative(jspmBaseUrl, pathRelativeToDir);
94+
}).then(function (relativeFilename) {
95+
return {
96+
expression: bundle.id,
97+
relativeFilename: relativeFilename
98+
};
99+
});
100+
})).then(function (modules) {
101+
return modules.reduce(function (accumulator, module) {
102+
accumulator[module.expression] = module.relativeFilename;
103+
return accumulator;
104+
}, {});
105+
});
106+
};
107+
88108
var writeBundlesConfig = function (bundles) {
89-
var bundlesConfig = bundles.reduce(function (accumulator, bundle) {
90-
accumulator[bundle.uri.replace('.js', '')] = [bundle.id];
91-
return accumulator;
92-
}, {});
93-
var configFilePath = path.join(jspmBaseUrl, 'systemjs-bundle-config.js');
94-
var configFileData = 'System.config({ bundles: ' + JSON.stringify(bundlesConfig, null, '\t') + ' })';
95-
console.log('writing to %s', configFilePath);
96-
fs.writeFileSync(configFilePath, configFileData);
109+
return createModuleExpressionToFilenameMap(bundles).then(function (map) {
110+
var bundlesConfig = bundles.reduce(function (accumulator, bundle) {
111+
accumulator[map[bundle.id]] = bundle.uri;
112+
return accumulator;
113+
}, {});
114+
var filePath = path.join(prefixPath, 'assets/jspm-assets.map');
115+
var fileData = JSON.stringify(bundlesConfig, null, '\t');
116+
console.log('writing to %s', filePath);
117+
fs.writeFileSync(filePath, fileData);
118+
});
97119
};
98120

99121
Promise.all(bundleConfigs.map(createBundle))
100122
.then(function (bundles) {
101123
writeBundlesToDisk(bundles);
102-
writeBundlesConfig(bundles);
124+
return writeBundlesConfig(bundles);
103125
})
104126
.catch(function (error) {
105127
console.error(error.stack);

‎common/app/assets/assets.scala‎

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import java.net.URL
55
import common.{Logging, RelativePathEscaper}
66
import conf.Configuration
77
import org.apache.commons.io.IOUtils
8-
import play.api.libs.json.{JsObject, JsString, Json}
8+
import play.api.libs.json._
99
import play.api.{Mode, Play}
1010

1111
import scala.collection.concurrent.{Map => ConcurrentMap, TrieMap}
@@ -144,14 +144,30 @@ class Assets(base: String, assetMap: String = "assets/assets.map") extends Loggi
144144
private def inlineJs(path: String): String = IOUtils.toString(AssetFinder(path))
145145

146146
val curl: String = RelativePathEscaper.escapeLeadingDotPaths(inlineJs("assets/curl-domReady.js"))
147+
}
148+
149+
object systemJs {
150+
private def contents(path: String): String = IOUtils.toString(AssetFinder(path))
151+
152+
val main: String = contents("assets/system.src.js")
153+
val polyfills: String = contents("assets/system-polyfills.src.js")
154+
val appConfig: String = contents("assets/systemjs-config.js")
155+
val normalize: String = contents("assets/systemjs-normalize.js")
156+
157+
lazy val setupFragment: String = templates.js.systemJsSetup().body
147158

148-
val systemJsPolyfills: String = inlineJs("assets/system-polyfills.src.js")
149-
val systemJs: String = inlineJs("assets/system.src.js")
150-
val systemJsAppConfig: String = inlineJs("assets/systemjs-config.js")
151-
val systemJsNormalize: String = inlineJs("assets/systemjs-normalize.js")
152-
val systemJsBundleConfig: String = inlineJs("assets/systemjs-bundle-config.js")
159+
private val jspmAssetMap: Map[String, String] =
160+
Json.parse(contents("assets/jspm-assets.map")).validate[Map[String, String]] match {
161+
case JsSuccess(m, _) => m
162+
case JsError(_) => Map.empty
163+
}
164+
165+
private val bundleConfigMap: Map[String, List[String]] =
166+
jspmAssetMap.map { case (source, destination) =>
167+
(destination.replaceFirst(".js$", ""), List(source.replaceFirst("^javascripts/", "").replaceFirst(".js$", "")))
168+
}
153169

154-
lazy val systemJsSetupFragment: String = templates.js.systemJsSetup().body
170+
val bundleConfig: String = Json.toJson(bundleConfigMap).toString()
155171
}
156172
}
157173

0 commit comments

Comments
 (0)

Footer

© 2026 GitHub, Inc.

Back | FazBrowse Home | New Git URL