Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1757 tm new routing #342

Closed
wants to merge 20 commits into from
Closed
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ node_modules/
.idea/
wwwroot/build/
wwwroot/doc/
wwwroot/prerendered/
npm-debug.log
version.js
wwwroot/init/nm.json
Expand All @@ -17,6 +18,7 @@ datasources/00_National_Data_Sets.json
/error.log
/output.log
privateserverconfig.json
wwwroot/sitemap.xml
wwwroot/privateconfig.json
deploy/packages/
deploy/work/
Expand Down
8 changes: 8 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
language: node_js
dist: trusty
addons:
apt:
packages:
- libnss3
node_js:
- '8'
script:
- gulp lint release
env:
- NODE_OPTIONS=--max_old_space_size=2048
before_install:
# Enable user namespace cloning
- "sysctl kernel.unprivileged_userns_clone=1"
51 changes: 51 additions & 0 deletions buildprocess/generate-init-routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
var fs = require("fs");
var path = require("path");
var URI = require("urijs");
var CATALOG_ROUTE = require("terriajs/lib/ReactViewModels/TerriaRouting").CATALOG_ROUTE;

const rootGroupName = "Root Group";

const getNameFromItem = item => item.name;
const getIdFromItem = item => item.id;


const getRoutes = (topCatalogItem, currentRoute = rootGroupName) =>
topCatalogItem.reduce((acc, catalogItem) => {
const nameForCurrentItem = getNameFromItem(catalogItem);
// Id is used for uniqueid, so disregard any pathing
const idFromItem = getIdFromItem(catalogItem);
const finalRoute = idFromItem || `${currentRoute}/${nameForCurrentItem}`;
const items = catalogItem.items && getRoutes(catalogItem.items, finalRoute);

if (items) {
return [...acc, ...items, finalRoute];
}
return [...acc, finalRoute];
}, []);
/**
* Given an array of init names for files in wwwroot/init/, traverse the catalog
* and generate a list of routes to be prerendered at build time
*
* @param {Array} initUrls
*/
function generateRoutes(initUrls) {
const resUrl = url =>
path.resolve(__dirname, "..", "wwwroot", "init", `${url}.json`);

const getCatalogFromInitName = initName => resUrl(initName);

const routesFromInitCatalogs = initUrls.reduce((acc, initName) => {
const fsPathForInit = getCatalogFromInitName(initName);
const data = fs.readFileSync(fsPathForInit, "utf8");
const literal = JSON.parse(data).catalog;

return [...acc, ...getRoutes(literal, `${rootGroupName}`)];
}, []);

const encodedRoutes = routesFromInitCatalogs.map(route => `${CATALOG_ROUTE}${URI.encode(route)}`);

// Make sure we also prerender /catalog/ incase user reloads on it? or serve up in terriajs server?
return [CATALOG_ROUTE, ...encodedRoutes];
}

module.exports = generateRoutes;
35 changes: 35 additions & 0 deletions buildprocess/generate-terria-sitemap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const generateUrl = (loc, lastmod, changefreq, priority) => (`
<url>
<loc>${loc}</loc>
<lastmod>${lastmod}</lastmod>
<changefreq>${changefreq}</changefreq>
<priority>${priority}</priority>
</url>
`);

/**
* Generate a sitemap to be written out during build
*
* @param {string} baseUrl absolute URL to where your map is going to be deployed to, with a trailing slash
* @param {array} catalogRoutes list of routes, e.g. ['/catalog', '/catalog/someId']
*/
const generateTerriaSitemap = (baseUrl, catalogRoutes) => {
if (typeof baseUrl !== 'string') {
throw 'baseUrl passed to generateTerriaSitemap is not a string?';
}
if (baseUrl.substr(0,4) !== 'http') {
throw 'baseUrl does not look absolute, check that it begins with http or https';
}
const baseUrlWithoutTrailingSlash = (baseUrl.substr(-1) === '/') ? baseUrl.slice(0,-1) : baseUrl;
const date = new Date().toISOString().substr(0, 10);

const start = '<?xml version="1.0" encoding="UTF-8"?>';
const urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
const urlsetEnd = `</urlset>`;
const homeUrl = generateUrl(baseUrl, date, 'daily', '0.9');
const routeUrls = catalogRoutes.map(route => generateUrl(`${baseUrlWithoutTrailingSlash}${route}`, date, 'weekly', '0.5'));

return `${start}${urlsetStart}${homeUrl}${routeUrls.join('')}${urlsetEnd}`;
};

module.exports = generateTerriaSitemap;
52 changes: 52 additions & 0 deletions buildprocess/webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
'use strict';

/*global require*/
var fs = require('fs');
var configureWebpackForTerriaJS = require('terriajs/buildprocess/configureWebpack');
var MiniCssExtractPlugin = require('mini-css-extract-plugin');
var generateRoutes = require("./generate-init-routes");
var generateTerriaSitemap = require("./generate-terria-sitemap");
var PrerenderSPAPlugin = require("prerender-spa-plugin");
var Renderer = PrerenderSPAPlugin.PuppeteerRenderer;
var path = require('path');
var json5 = require("json5");

module.exports = function(devMode, hot) {
var config = {
Expand Down Expand Up @@ -108,5 +114,51 @@ module.exports = function(devMode, hot) {
}
};
config.resolve.alias['terriajs-variables'] = require.resolve('../lib/Styles/variables.scss');

if (!devMode) {
var configJsonPath = fs.readFileSync(path.resolve(__dirname, '..','wwwroot', 'config.json'), 'utf8');
var configJson = json5.parse(configJsonPath);
var prerenderRoutes =
(configJson &&
configJson.initializationUrls &&
configJson.initializationUrls.length > 0 &&
generateRoutes(configJson.initializationUrls)) ||
[];
var appBaseUrl =
(configJson &&
configJson.parameters &&
configJson.parameters.appBaseUrl &&
configJson.parameters.appBaseUrl.length > 0 &&
configJson.parameters.appBaseUrl);

console.log('The following routes generated from config.json\'s initializationUrls will be prerendered:');
console.log(prerenderRoutes);

if (appBaseUrl) {
try {
console.log('Attempting to write sitemap with appBaseUrl: ', appBaseUrl);
var sitemap = generateTerriaSitemap(appBaseUrl, prerenderRoutes);
var sitemapPath = path.resolve(__dirname, '..', 'wwwroot', 'sitemap.xml');
fs.writeFileSync(sitemapPath, new Buffer(sitemap));
console.log('Wrote out sitemap to: ' + sitemapPath);
} catch (e) {
console.error("Couldn't generate sitemap?", e);
}
} else {
console.warn("Warning - no appBaseUrl specified, no sitemap will be generated.")
}
config.plugins = [...config.plugins, new PrerenderSPAPlugin({
staticDir: path.resolve(__dirname, '..', 'wwwroot', ),
outputDir: path.resolve(__dirname, '..', 'wwwroot', 'prerendered'),
indexPath: path.resolve(__dirname, '..', 'wwwroot', 'index.html'),
routes: prerenderRoutes,
renderer: new Renderer({
renderAfterDocumentEvent: 'prerender-end',
// If you run out of memory, try a lower value here
maxConcurrentRoutes: 8,
// headless: false, // set to false for debugging
}),
})];
}
return configureWebpackForTerriaJS(path.dirname(require.resolve('terriajs/package.json')), config, devMode, hot, MiniCssExtractPlugin);
};
2 changes: 2 additions & 0 deletions deploy/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
FROM node:8

RUN apt-get update && apt-get install -y gdal-bin
RUN apt-get -qq -y install gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget


RUN mkdir -p /usr/src/app && mkdir -p /etc/config/client
WORKDIR /usr/src/app/component
Expand Down
2 changes: 2 additions & 0 deletions devserverconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"port": 3001,

"baseHref": "/",

"allowProxyFor" : [
"nicta.com.au",
"gov.au",
Expand Down
25 changes: 22 additions & 3 deletions entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ function loadMainScript() {
}

function createLoader() {
// We only want this briefly so the explorer-window modal can be displayed
// until we load in other modal-like-things like disclaimer windows,
// but also other notification windows like error messages
// So, reset it back to app defaults after
const catalogzIndexOverride = document.createElement('style');
catalogzIndexOverride.setAttribute('type', 'text/css');
catalogzIndexOverride.innerHTML = `
.tjs-explorer-window__modal-wrapper {
z-index:10000 !important;
}
`;
document.body.appendChild(catalogzIndexOverride);

const loaderDiv = document.createElement('div');
loaderDiv.classList.add("loader-ui");
const loaderGif = document.createElement('img');
Expand All @@ -34,10 +47,16 @@ function createLoader() {
loadMainScript().catch(() => {
// Ignore errors and try to show the map anyway
}).then(() => {
loaderDiv.classList.add('loader-ui-hide');
setTimeout(()=> {
const removeLoaderElements = () => {
document.body.removeChild(loaderDiv);
}, 2000);
document.body.removeChild(catalogzIndexOverride);
};
loaderDiv.classList.add('loader-ui-hide');
setTimeout(() => document.body.removeChild(catalogzIndexOverride), 300);
loaderDiv.addEventListener('transitionend', removeLoaderElements);
// also fallback with setTimeout here
// so we can remove the elements anyway in case of transitionend event failure
setTimeout(removeLoaderElements, 2000);
});
}

Expand Down
8 changes: 8 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,14 @@ function mergeConfigs(original, override) {
gulp.task('render-datasource-templates', function(done) {
var ejs = require('ejs');
var JSON5 = require('json5');
var serverConfig = JSON5.parse(fs.readFileSync('devserverconfig.json', 'utf8'));

var index = fs.readFileSync('wwwroot/index.ejs', 'utf8');
var baseHrefFromConfig = serverConfig.baseHref;
var indexResult = ejs.render(index, { baseHref: baseHrefFromConfig || "/"});

fs.writeFileSync(path.join('wwwroot', 'index.html'), new Buffer(indexResult));

var templateDir = 'datasources';
try {
fs.accessSync(templateDir);
Expand Down
1 change: 1 addition & 0 deletions lib/Styles/loader.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

.loader-ui{
transition: opacity, 2s;
transition-timing-function: cubic-bezier(.2,1.22,.83,.89);
opacity: 1;
height: 100vh;
width: 100vw;
Expand Down
2 changes: 1 addition & 1 deletion lib/Views/UserInterface.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import PropTypes from "prop-types";
import React from "react";
import RelatedMaps from "./RelatedMaps";
import SplitPoint from "terriajs/lib/ReactViews/SplitPoint";
import StandardUserInterface from "terriajs/lib/ReactViews/StandardUserInterface/StandardUserInterface.jsx";
import { StandardUserInterface } from "terriajs/lib/ReactViews/StandardUserInterface/StandardUserInterface.jsx";
import version from "../../version";

import "./global.scss";
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@
"node-notifier": "^5.1.2",
"node-sass": "^4.11.0",
"plugin-error": "^1.0.1",
"prerender-spa-plugin": "^3.4.0",
"prettier": "1.17.0",
"pretty-quick": "^1.10.0",
"prop-types": "^15.6.0",
"raw-loader": "^1.0.0",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-router-dom": "^5.0.0",
"redbox-react": "^1.3.6",
"resolve-url-loader": "^3.0.1",
"sass-loader": "^7.1.0",
Expand Down
4 changes: 4 additions & 0 deletions wwwroot/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
"terria"
],
parameters: {
// For sitemap.xml generation, specify the protocol + fully qualified domain
// name + path of where you'll be serving your site, e.g.:
// appBaseUrl: "https://nationalmap.gov.au/",

googleUrlShortenerKey: null,
googleAnalyticsKey: null,
googleAnalyticsOptions: null,
Expand Down
42 changes: 42 additions & 0 deletions wwwroot/index.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en" class="terria">
<head>
<base href="<%= baseHref %>">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"> <!-- Use Chrome Frame in IE -->
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="A web map built on Terria Map" data-react-helmet="true">
<meta name="copyright" content="Copyright(c) 2012-2016 National ICT Australia Limited (NICTA), CSIRO Data61. All rights reserved.">
<meta name="apple-mobile-web-app-capable" content="yes">

<link rel="apple-touch-icon" sizes="57x57" href="favicons/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="favicons/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="favicons/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="favicons/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="favicons/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="favicons/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="favicons/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="favicons/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="favicons/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="favicons/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="favicons/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="favicons/favicon-16x16.png">
<link rel="manifest" href="favicons/manifest.json">
<meta name="msapplication-TileColor" content="#282D32">
<meta name="msapplication-TileImage" content="favicons/ms-icon-144x144.png">
<meta name="theme-color" content="#282D32">

<title>Terria Map</title>

<!-- Leaflet -->
<script>L_PREFER_CANVAS = true;</script>
<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
</head>

<body>

<div id='ui'></div>
<script src="<%= baseHref %>build/TerriaMap.js"></script>
</body>
</html>
5 changes: 3 additions & 2 deletions wwwroot/index.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<!DOCTYPE html>
<html lang="en" class="terria">
<head>
<base href="/">
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually now index.html gets updated as part of the render-datasource-templates gulp task, should we remove this from source to avoid confusion?

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"> <!-- Use Chrome Frame in IE -->
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="A web map built on Terria Map">
<meta name="description" content="A web map built on Terria Map" data-react-helmet="true">
<meta name="copyright" content="Copyright(c) 2012-2016 National ICT Australia Limited (NICTA), CSIRO Data61. All rights reserved.">
<meta name="apple-mobile-web-app-capable" content="yes">

Expand Down Expand Up @@ -36,6 +37,6 @@
<body>

<div id='ui'></div>
<script src="build/TerriaMap.js"></script>
<script src="/build/TerriaMap.js"></script>
</body>
</html>