From 1b42953b33c289be98761921db8e84b9f8254d51 Mon Sep 17 00:00:00 2001 From: Emmanuel Luciano Date: Sat, 30 Jan 2016 09:50:36 -0400 Subject: [PATCH 01/10] Removes white space in addon name. --- app/helpers/split-prefix.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/split-prefix.js b/app/helpers/split-prefix.js index 4074af2..37eb4b6 100644 --- a/app/helpers/split-prefix.js +++ b/app/helpers/split-prefix.js @@ -16,7 +16,7 @@ export function splitPrefix(value) { const prefix = parts[1]; const name = Ember.Handlebars.Utils.escapeExpression(parts[2]); - return new Ember.Handlebars.SafeString(`${prefix} ${name}`); + return new Ember.Handlebars.SafeString(`${prefix}${name}`); } export default Ember.Helper.helper(splitPrefix); From 1a9ae9b2d4f59784205a70071df58594db821610 Mon Sep 17 00:00:00 2001 From: Emmanuel Luciano Date: Sat, 30 Jan 2016 11:18:29 -0400 Subject: [PATCH 02/10] Fixes layout break on long names --- app/styles/app.css | 19 +++++++++++++++++++ app/templates/components/em-pkg.hbs | 10 +++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/app/styles/app.css b/app/styles/app.css index fdd8bdf..08e13e9 100644 --- a/app/styles/app.css +++ b/app/styles/app.css @@ -152,11 +152,30 @@ a.sort-button { margin-top: 20px; } +.gravatar--wrapper { + display: inline; +} + .gravatar { border-radius: 50%; margin-right: 5px; } +.author-information { + display: inline-block; + vertical-align: middle; + max-width: 130px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + text-decoration: none; +} + +.author-information__anchor:hover { + text-decoration: none; + color: #D02714; +} + .package-link { font-size: 24px; } diff --git a/app/templates/components/em-pkg.hbs b/app/templates/components/em-pkg.hbs index fa0a748..1701e57 100644 --- a/app/templates/components/em-pkg.hbs +++ b/app/templates/components/em-pkg.hbs @@ -29,9 +29,13 @@ {{/if}} - - - {{user.name}} + +
+ +
+
+ {{user.name}} +
From 29fc504625c6d57cbf391177fbd92e685b889bdb Mon Sep 17 00:00:00 2001 From: Emmanuel Luciano Date: Wed, 6 Apr 2016 09:05:42 -0400 Subject: [PATCH 03/10] Installs broccoli-serviceworker and adds configuration. --- config/environment.js | 9 +++++++++ package.json | 1 + 2 files changed, 10 insertions(+) diff --git a/config/environment.js b/config/environment.js index 8c4b39e..b10859a 100644 --- a/config/environment.js +++ b/config/environment.js @@ -21,6 +21,15 @@ module.exports = function(environment) { 'ember-load': { loadingIndicatorClass: 'ember-load-indicator' + }, + + serviceWorker: { + enabled: true, + debug: true, + excludePaths: ['test.*', 'robots.txt'], + includeRegistration: true, + serviceWorkerFile: 'sw.js', + skipWaiting: false } }; diff --git a/package.json b/package.json index ed2ba5c..b09d07b 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "license": "MIT", "devDependencies": { "broccoli-asset-rev": "^2.2.0", + "broccoli-serviceworker": "0.1.0", "ember-cli": "1.13.15", "ember-cli-app-version": "^1.0.0", "ember-cli-babel": "^5.1.5", From 5a54d2e6fef46fbf97ec118c99b0731c9ebb306e Mon Sep 17 00:00:00 2001 From: Emmanuel Luciano Date: Wed, 6 Apr 2016 09:06:03 -0400 Subject: [PATCH 04/10] Adds custom logic to service worker. --- app/serviceworkers/sw.js | 61 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 app/serviceworkers/sw.js diff --git a/app/serviceworkers/sw.js b/app/serviceworkers/sw.js new file mode 100644 index 0000000..b936d6b --- /dev/null +++ b/app/serviceworkers/sw.js @@ -0,0 +1,61 @@ +const addonsLink = 'https://io-builtwithember-addons-data.s3.amazonaws.com/addons.json'; +const GRAVATAR_CACHE = 'GRAVATAR_URLS'; + +toolbox.router.get('/addons/json', toolbox.networkFirst, {origin: 'https://io-builtwithember-addons-data.s3.amazonaws.com'}); +toolbox.precache(addonsLink); + + +// Request the addons.js, filter the gravatar ulrs and return an array of gravatar urls. +function gravatarUrls() { + return fetch(addonsLink).then(function(response) { + return response.json(); + }).then(function(json) { + return json.map(function(curr) { + return curr['_npmUser'].gravatar + '?s=30&d=retro'; + }).filter(function(data, index, array) { + if (array.indexOf(data) === index) { + return data; + } + }); + }); +} + +// Go through every gravatar url and remove the origin. +function addGravatarUrlsToRouter(urls) { + const gravatarUrl = 'https://secure.gravatar.com'; + const regex = /https:\/\/secure.gravatar.com/g; + + urls.forEach(function(url) { + const gravatarPath = url.replace(regex, ''); + + toolbox.router.get(gravatarPath, toolbox.cacheFirst, {origin: gravatarUrl}); + }); +} + +// waitUntil expects a promise and it will stop the worker execution +// until the promise is resolved. +self.addEventListener('install', function(event) { + event.waitUntil( + gravatarUrls().then(function(urls) { + addGravatarUrlsToRouter(urls); + + // Open the specified cache if it exists. If the cache doesn't exist + // create it and add prefetch the urls on the array. + caches.open(GRAVATAR_CACHE).then(function(cache) { + cache.addAll(urls); + }); + }) + ); +}); + +// Intercept every request that the app makes. If it the request matches +// a request that has been stored in the cache return the response that is stored. +self.addEventListener('fetch', function(event) { + event.respondWith( + caches.match(event.request).then(function(res) { + if (res) { + return res; + } + }) + ); +}); From 54cac44814fc0128ed0ef19aa8ec8f52caa4f055 Mon Sep 17 00:00:00 2001 From: Emmanuel Luciano Date: Wed, 6 Apr 2016 10:14:38 -0400 Subject: [PATCH 05/10] Changes environment config. --- config/environment.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/environment.js b/config/environment.js index b10859a..50ebcd7 100644 --- a/config/environment.js +++ b/config/environment.js @@ -29,7 +29,7 @@ module.exports = function(environment) { excludePaths: ['test.*', 'robots.txt'], includeRegistration: true, serviceWorkerFile: 'sw.js', - skipWaiting: false + skipWaiting: true } }; From 2a43c3c3d90b799fb23ac0c5df3b4e62f24854c7 Mon Sep 17 00:00:00 2001 From: Emmanuel Luciano Date: Wed, 6 Apr 2016 10:15:32 -0400 Subject: [PATCH 06/10] Comments addGravatarUrlsToRouter function and adds skipWaiting. --- app/serviceworkers/sw.js | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/app/serviceworkers/sw.js b/app/serviceworkers/sw.js index b936d6b..1fd0a12 100644 --- a/app/serviceworkers/sw.js +++ b/app/serviceworkers/sw.js @@ -4,7 +4,6 @@ const GRAVATAR_CACHE = 'GRAVATAR_URLS'; toolbox.router.get('/addons/json', toolbox.networkFirst, {origin: 'https://io-builtwithember-addons-data.s3.amazonaws.com'}); toolbox.precache(addonsLink); - // Request the addons.js, filter the gravatar ulrs and return an array of gravatar urls. function gravatarUrls() { return fetch(addonsLink).then(function(response) { @@ -21,16 +20,16 @@ function gravatarUrls() { } // Go through every gravatar url and remove the origin. -function addGravatarUrlsToRouter(urls) { - const gravatarUrl = 'https://secure.gravatar.com'; - const regex = /https:\/\/secure.gravatar.com/g; +// function addGravatarUrlsToRouter(urls) { +// const gravatarUrl = 'https://secure.gravatar.com'; +// const regex = /https:\/\/secure.gravatar.com/g; - urls.forEach(function(url) { - const gravatarPath = url.replace(regex, ''); +// urls.forEach(function(url) { +// const gravatarPath = url.replace(regex, ''); - toolbox.router.get(gravatarPath, toolbox.cacheFirst, {origin: gravatarUrl}); - }); -} +// toolbox.router.get(gravatarPath, toolbox.cacheFirst, {origin: gravatarUrl}); +// }); +// } // waitUntil expects a promise and it will stop the worker execution // until the promise is resolved. @@ -44,6 +43,10 @@ self.addEventListener('install', function(event) { caches.open(GRAVATAR_CACHE).then(function(cache) { cache.addAll(urls); }); + + if (self.skipWaiting) { + self.skipWaiting(); + } }) ); }); From 60b32e0186466468b8f0c972e92f4d37be1c1e5f Mon Sep 17 00:00:00 2001 From: Emmanuel Luciano Date: Wed, 6 Apr 2016 10:33:17 -0400 Subject: [PATCH 07/10] Comments unnecessary function call --- app/serviceworkers/sw.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/serviceworkers/sw.js b/app/serviceworkers/sw.js index 1fd0a12..f934b1b 100644 --- a/app/serviceworkers/sw.js +++ b/app/serviceworkers/sw.js @@ -36,7 +36,7 @@ function gravatarUrls() { self.addEventListener('install', function(event) { event.waitUntil( gravatarUrls().then(function(urls) { - addGravatarUrlsToRouter(urls); + // addGravatarUrlsToRouter(urls); // Open the specified cache if it exists. If the cache doesn't exist // create it and add prefetch the urls on the array. From 91a8db614cc2dc884c9dcb37dac13d6c7dcd7cff Mon Sep 17 00:00:00 2001 From: Emmanuel Luciano Date: Wed, 6 Apr 2016 10:34:17 -0400 Subject: [PATCH 08/10] Removes typo. --- app/serviceworkers/sw.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/serviceworkers/sw.js b/app/serviceworkers/sw.js index f934b1b..0fd5b04 100644 --- a/app/serviceworkers/sw.js +++ b/app/serviceworkers/sw.js @@ -1,7 +1,7 @@ const addonsLink = 'https://io-builtwithember-addons-data.s3.amazonaws.com/addons.json'; const GRAVATAR_CACHE = 'GRAVATAR_URLS'; -toolbox.router.get('/addons/json', toolbox.networkFirst, {origin: 'https://io-builtwithember-addons-data.s3.amazonaws.com'}); +toolbox.router.get('/addons.json', toolbox.networkFirst, {origin: 'https://io-builtwithember-addons-data.s3.amazonaws.com'}); toolbox.precache(addonsLink); // Request the addons.js, filter the gravatar ulrs and return an array of gravatar urls. From 4d4b5a65475a28a02d80cdb47b1071bc7b758280 Mon Sep 17 00:00:00 2001 From: Emmanuel Luciano Date: Sat, 9 Apr 2016 20:07:31 -0400 Subject: [PATCH 09/10] Modifies changes to custom logic in service worker. --- app/serviceworkers/sw.js | 56 +++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/app/serviceworkers/sw.js b/app/serviceworkers/sw.js index 0fd5b04..6742292 100644 --- a/app/serviceworkers/sw.js +++ b/app/serviceworkers/sw.js @@ -1,16 +1,16 @@ -const addonsLink = 'https://io-builtwithember-addons-data.s3.amazonaws.com/addons.json'; +const addonsUrl = 'https://io-builtwithember-addons-data.s3.amazonaws.com/addons.json'; const GRAVATAR_CACHE = 'GRAVATAR_URLS'; toolbox.router.get('/addons.json', toolbox.networkFirst, {origin: 'https://io-builtwithember-addons-data.s3.amazonaws.com'}); -toolbox.precache(addonsLink); +toolbox.precache(addonsUrl); // Request the addons.js, filter the gravatar ulrs and return an array of gravatar urls. function gravatarUrls() { - return fetch(addonsLink).then(function(response) { + return fetch(addonsUrl).then(function(response) { return response.json(); }).then(function(json) { return json.map(function(curr) { - return curr['_npmUser'].gravatar + '?s=30&d=retro'; + return curr['_npmUser'].gravatar ? curr['_npmUser'].gravatar + '?s=30&d=retro':''; }).filter(function(data, index, array) { if (array.indexOf(data) === index) { return data; @@ -20,45 +20,47 @@ function gravatarUrls() { } // Go through every gravatar url and remove the origin. -// function addGravatarUrlsToRouter(urls) { -// const gravatarUrl = 'https://secure.gravatar.com'; -// const regex = /https:\/\/secure.gravatar.com/g; - -// urls.forEach(function(url) { -// const gravatarPath = url.replace(regex, ''); - -// toolbox.router.get(gravatarPath, toolbox.cacheFirst, {origin: gravatarUrl}); -// }); -// } +function isGravatarUrl(url) { + return url.indexOf('https://secure.gravatar.com'); +} // waitUntil expects a promise and it will stop the worker execution // until the promise is resolved. self.addEventListener('install', function(event) { event.waitUntil( gravatarUrls().then(function(urls) { - // addGravatarUrlsToRouter(urls); - // Open the specified cache if it exists. If the cache doesn't exist // create it and add prefetch the urls on the array. caches.open(GRAVATAR_CACHE).then(function(cache) { cache.addAll(urls); }); - - if (self.skipWaiting) { - self.skipWaiting(); - } }) ); }); -// Intercept every request that the app makes. If it the request matches -// a request that has been stored in the cache return the response that is stored. +/** + Intercept every request that the app makes. If it the request matches + a request that has been stored in the cache return the response that is stored. + + If the request is not in the caches and if it's a new gravatar then fetch the new + gravatar and add it to the gravatars cache. After storing the response in the cache + we return a clone of the response to the app. +*/ self.addEventListener('fetch', function(event) { event.respondWith( - caches.match(event.request).then(function(res) { - if (res) { - return res; - } - }) + caches.match(event.request) + .then(function(res) { + if (res) { + return res; + } else if (isGravatarUrl(event.request.url) >= 0) { + return fetch(event.request.url).then(function(response) { + caches.open(GRAVATAR_CACHE).then(function(cache) { + cache.put(event.request, response); + }); + + return response.clone(); + }); + } + }) ); }); From fbd60988d3f1fca46157c7ac1d7f99d7c4bfb8e9 Mon Sep 17 00:00:00 2001 From: Emmanuel Luciano Date: Sat, 9 Apr 2016 20:38:59 -0400 Subject: [PATCH 10/10] Adds some comments to functions --- app/serviceworkers/sw.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/app/serviceworkers/sw.js b/app/serviceworkers/sw.js index 6742292..23f202c 100644 --- a/app/serviceworkers/sw.js +++ b/app/serviceworkers/sw.js @@ -1,6 +1,13 @@ const addonsUrl = 'https://io-builtwithember-addons-data.s3.amazonaws.com/addons.json'; const GRAVATAR_CACHE = 'GRAVATAR_URLS'; +/** + The addons url variable will return the addons.json that the app needs. + We will add this url to the broccoli-sw. The broccoli-sw uses sw-toolbox. + The sw-toolbox gives us handler functions that we can use to manage the request. + + We are using the networkFirst strategy in order to keep this file updated. +*/ toolbox.router.get('/addons.json', toolbox.networkFirst, {origin: 'https://io-builtwithember-addons-data.s3.amazonaws.com'}); toolbox.precache(addonsUrl); @@ -24,13 +31,18 @@ function isGravatarUrl(url) { return url.indexOf('https://secure.gravatar.com'); } -// waitUntil expects a promise and it will stop the worker execution -// until the promise is resolved. +/** + waitUntil expects a promise and it will stop the worker execution until the promise is resolved. + The gravatarUrls will fetch the addons.json file and filter the users gravatars. + When we have the array of urls we open or create the gravatar cache and add the urls. +*/ self.addEventListener('install', function(event) { event.waitUntil( gravatarUrls().then(function(urls) { - // Open the specified cache if it exists. If the cache doesn't exist - // create it and add prefetch the urls on the array. + /** + Open the specified cache if it exists. If the cache doesn't exist + create it and add prefetch the urls on the array. + */ caches.open(GRAVATAR_CACHE).then(function(cache) { cache.addAll(urls); });