Update Workbox controlled pre-cached items in "installed" (added to home screen) PWA - offline

I am using Workbox 2 to deal with "offline" behavior of my PWA. The content is produced by HexoJS and is deployed to GitHub Pages. Here is the workbox-cli-config.js for reference:
module.exports = {
globDirectory: "./public/",
globPatterns: ["**/*.html", "**/*.js", "**/*.css", "**/*.png"],
swDest: "public/sw.js",
clientsClaim: true,
skipWaiting: true,
runtimeCaching: [
{
urlPattern: /^https:\/\/use\.fontawesome\.com\/releases/,
handler: "networkFirst"
},
{
urlPattern: /^https:\/\/fonts\.gstatic\.com\/s\//,
handler: "networkFirst"
},
{
urlPattern: /^https:\/\/maxcdn\.bootstrapcdn\.com\/bootstrap/,
handler: "networkFirst"
},
{
urlPattern: /^https:\/\/fonts\.googleapis\.com/,
handler: "networkFirst"
},
{
urlPattern: /^https:\/\/code\.jquery\.com\/jquery-3/,
handler: "networkFirst"
},
]
};
Everything works as expected and the app properly handles switch to the offline mode in Chrome DevTools.
The problem shows up when I update some static content, say HTML, and re-deploy it onto the GitHub pages --- I can see the updated version of the content but not always, and not in all browsers.
I always have to use "Clear browsing data" action in Opera or Chrome (or other browsers) to refresh the appearance of the page, because simple "Refresh/reload" doesn't help.
The problem gets even worser with the "Added to home screen" PWA. I cannot enforce content refresh even by doing uninstall/reinstall. Only wiping off browsing data in Android Chrome browser helps to refresh app content.
My questions are:
Is it possible at all to let pre-cached static assets being automatically updated when I re-visit the page or refresh the installed PWA?
Am I configuring Workbox in a wrong way (see my workbox-cli-config.js above)
Will migration to Workbox 3 make any difference?
I'd be glad to share other config files if this will help to resolve to problem.
PS: The page has the score of 100 in Lighthouse for all criteria except for performance (because of loading blocking content of bootstrap.min.js but read in SO that this is OK).

Related

In wagtail how do I setup the v2 api to attach the full base url ( e.g. http://localhost:8000" ) to steamfield images and richtext embeds?

I am currently using nuxt.js as a frontend for my wagtail headless cms. When I load a richtext field or an image block within a streamfield I am unable, or don't know how to, attach the full base url of the wagtail server so when it gets rendered on the nuxtjs site it resolves to src="/media/images/image.png which in the end tries to find the image on the nuxtjs site http://localhost:3000 and it needs to find it on the wagtail server side http://localhost:8000. For standard images I can intercept and prepend the server base url, but not when it comes to anything inside a streamfield.
[EDIT: Better answer below]
I'm not 100% certain this is the "proper" way to do it, but I managed to get what I needed by adding a server middleware that detects anything that starts with the directory /media and prepends the server base url.
// in nuxt.config.js
export default {
serverMiddleware:[
'~/serverMiddleware/redirects'
],
}
then in `serverMiddleware/redirects.js
export default function(req, res, next) {
if (req.url.startsWith('/media')) {
res.writeHead(301, {Location: `http://localhost:8000${req.url}`})
res.end()
} else {
next()
}
}
This is a quick workaround for now I'll see if there is anything better.
Ok, I believe this is the proper solution. It just seemed to evade me :P
Instead of using a redirect simply add a proxy to nuxt.config.js
modules: [
'#nuxtjs/axios',
],
axios: {proxy: true},
proxy: {
'/api/v2/': 'http://localhost:8000',
'/media/': 'http://localhost:8000'
}

How to have Google Form submit event trigger be caught by a Flask website to update that website?

I have a website written on Flask, and I would like to update it when answers to a Google Form has been submitted.
More precisely, I have already associated the form to a Google spreadsheet and I can read that spreadsheet from Flask, but the key component missing is how to trigger the website to update its content when new answers have been submitted to the form.
What would be the best way to do this?
Webhook solution:
Google Forms:
Enter the Google Forms editor
Click 3 vertical dots next to profile picture, and select 'script editor'
Customize this snippet to your WebHook url and set a custom token (this is not really secure, but better than nothing ).
function onFormSubmit(e) {
const url = "https://example.com/webhook";
var options = {
"method": "post",
"headers": {
"Content-Type": "application/json"
},
"payload": JSON.stringify({"token": "sometokenheretocheckonbackend"})
};
UrlFetchApp.fetch(url, options);
}
( Dialog may popup where you have to approve that you connect to an unauthorized service )
Handling on the Flask side:
from http import HTTPStatus
from flask import (
abort,
request
)
#blueprint.route('/webhook', methods=['POST'])
def handle_webhook():
payload = request.get_json()
if payload.get('token') != "sometokenheretocheckonbackend":
abort(HTTPStatus.UNAUTHORIZED)
# Update your content
return jsonify({'success': True}), HTTPStatus.OK
Periodic updates (Alternative solution):
I would consider launching a daemon Thread that periodically updates this content. This is obviously not as elegant, but should work quite stable and wouldn't be much more demanding for the server if the content update procedure is reasonably lightweight.
You could create an Form Submit trigger to trigger a Google Apps Script function that calls out to your Flask site and triggers the update.
https://developers.google.com/apps-script/guides/triggers/installable

How to embed an Apache Superset dashboard in a webpage?

I am trying to implement the Apache superset dashboard in a webpage.
Anyone have any idea how to implement this?
Keep the iframe tag line as you mentioned.
<iframe src="linkToYourDashBoard?standalone=true"></iframe>
and check the superset_config.py file.
HTTP_HEADERS = {'X-Frame-Options': 'SAMEORIGIN'}
Change the line to
HTTP_HEADERS = {'X-Frame-Options': 'ALLOWALL'}
or
HTTP_HEADERS = {}
Don't forget to add superset_config.py file to your python path.
First, you need to update the public roles with these options.
Security/List Roles:
can explore json on Superset,
can dashboard on Superset,
all database access on all_database_access
Second, embed your dashboard in your HTML
<iframe src="localhost:8088/superset/dashboard/5/?standalone=true"></iframe>
Superset Embedded SDK allows you to embed
dashboards from Superset into your own app, using your app's authentication.
superset backend server: update superset_config.py or config.py
FEATURE_FLAGS = {
"EMBEDDED_SUPERSET": True, # requirement
}
"GUEST_ROLE_NAME": "Public", # you might need to edit role permissions when 403 error
"GUEST_TOKEN_JWT_EXP_SECONDS": 300 # 5 minutes, or you could set it longer
your app's backend server
fetch access_token
http://localhost:8088/api/v1/security/login
fetch guest_token
http://localhost:8088/api/v1/security/guest_token/
your app's frontend, for example:
<script src="https://unpkg.com/#superset-ui/embedded-sdk"></script>
<script>
supersetEmbeddedSdk.embedDashboard({
id: 'd3918020-0349-435d-9277-xxxxxx', // given by the Superset embedding UI
supersetDomain: 'http://localhost:9000',
mountPoint: document.getElementById('container'), // any html element that can contain an iframe
fetchGuestToken: () =>
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.xxxxxx.1RExnlLfdDI6P4vG3gB0otLL7XR_3OE2OZ0WhCKyTyE', // guest_token
dashboardUiConfig: {} // dashboard UI config: hideTitle, hideTab, hideChartControls (optional)
})
</script>
Please refer to: Embedding Superset dashboards in your React application
Superset now provides the Superset Embedded SDK, an NPM package for inserting an iframe that will embed your Superset dashboard. I'm using it at the moment and it is relatively straightforward; this is the current implementation example provided in the docs:
import { embedDashboard } from "#superset-ui/embedded-sdk";
embedDashboard({
id: "abc123", // given by the Superset embedding UI
supersetDomain: "https://superset.example.com",
mountPoint: document.getElementById("my-superset-container"), // any html element that can contain an iframe
fetchGuestToken: () => fetchGuestTokenFromBackend(),
dashboardUiConfig: { hideTitle: true }, // dashboard UI config: hideTitle, hideTab, hideChartControls (optional)
});
Obviously the end result could still be achieved by adding the iframe "manually," but using the official abstraction might provide simplicity and future functionality in subsequent versions.

Strongloop / Loopback Getting started missing root.js

I'm following the getting started documentation from Loopback, and I have an issue when I want to add static files Strongloop getting started Step 3: the file /server/boot/root.js doesn't exists, in addition /server/server.js does not have the 2 lines that were supposed to be there :
// var path = require('path');
// app.use(loopback.static(path.resolve(__dirname, '../client')));
Instead, the /server/middleware.json shows :
"routes": {
"loopback#status": {
"paths": "/"
}
},
Could someone please let me know how to perform this step ? Note : the git repository for Step 3 is good, but not the scaffolded project running slc loopback.
The /server/middleware.json file is where middleware is registered now. The following excerpt is resolving to a file in module's server/middleware directory (loopback-getting-started/node_modules/loopback/server/middleware).
"routes": {
"loopback#status": {
"paths": "/"
}
},
Change this to:
"routes": {
},
Restart the Loopback server and visiting localhost:3000 results in an Express error 404, which would be expected since you no longer have a route defined for /.
You now need to specify in the middleware.json file how to serve static content. You do this in the "files" phase:
"files": {
"loopback#static": {
"params": "$!../client"
}
}
You can now add the following to an index.html file in your /client directory as the original documentation states.
<head><title>LoopBack</title></head>
<body>
<h1>LoopBack Rocks!</h1>
<p>Hello World... </p>
</body>
Restarting the Loopback server and visiting localhost:3000 now serves the index.html page.
More details about how to specify middleware via the new way is located at http://docs.strongloop.com/display/public/LB/Defining+middleware#Definingmiddleware-Registeringmiddlewareinmiddleware.json
Also see https://github.com/strongloop/loopback-faq-middleware
The latest version of LoopBack removed the root.js file. You do not need it anymore, the docs need to be updated to reflect this.

fb.ui feed dialog not working well on IOS

I used FB.ui to create a share dialog.
Here my coffeescript code:
FB.ui
method: "feed"
link: "facebook.com"
, (response) ->
if response and response.post_id
console.log("shared")
It works well on desktop browser and android but it doesn't work well on IOS (Safari & Chrome).
Problem is:
when i didn't sign in my facebook account and then I click share, it will redirect to new tab and request to login, after that I can share.
but when my facebook account sign in ready and then I click share, it doesn't show share dialog. it show only blank page.
Anyone ever meet this? How can I solve this???
Try add this to the code:
display: 'touch'
I was using
FB.ui(
{
method: 'share',
href: url,
mobile_iframe: true
},
function(response){
document.location.href = url;
});
But didn't work on iPhone so I decided to redirect the browser to the share url of Facebook like this:
document.location.href = 'https://www.facebook.com/dialog/feed?app_id=APPID&display=popup&&link=https%3A%2F%2Fyourdomain.com%2Furl&redirect_uri=https%3A%2F%2Fyourdomain.com.com%2Furl
Keep in mind that for : the code is %3A and / %2F. You will have to replace as such for it to pick them up.
Hope it helps