diff options
| -rw-r--r-- | cli/commands/site/export.py | 38 | ||||
| -rw-r--r-- | frontend/common/index.js | 3 | ||||
| -rw-r--r-- | frontend/common/loader.component.js | 16 | ||||
| -rw-r--r-- | frontend/common/miscellaneous.component.js | 11 | ||||
| -rw-r--r-- | frontend/site/site/site.actions.js | 20 | ||||
| -rw-r--r-- | frontend/site/viewer/viewer.container.js | 2 | ||||
| -rw-r--r-- | frontend/views/page/components/tile.handle.js | 2 | ||||
| -rw-r--r-- | frontend/views/page/cursors.css | 15 | ||||
| -rw-r--r-- | frontend/views/page/page.container.js | 1 | ||||
| -rw-r--r-- | frontend/views/page/page.css | 15 | ||||
| -rw-r--r-- | static/site.css | 129 | ||||
| -rw-r--r-- | static/site.html | 1 | ||||
| -rw-r--r-- | webpack.config.prod.js | 5 | ||||
| -rw-r--r-- | webpack.config.site.js | 55 |
14 files changed, 244 insertions, 69 deletions
diff --git a/cli/commands/site/export.py b/cli/commands/site/export.py index cf6be7b..d715c6c 100644 --- a/cli/commands/site/export.py +++ b/cli/commands/site/export.py @@ -3,6 +3,7 @@ import click from app.settings import app_cfg from app.utils.file_utils import load_text, write_json, write_text from os.path import join +import os @click.command('info') @click.option('-g', '--graph', 'opt_graph_path', required=True, @@ -17,6 +18,7 @@ def cli(ctx, opt_graph_path, opt_output_dir): # imports from app.sql.common import db, Session, Graph, Page, Tile + from distutils.dir_util import copy_tree # ------------------------------------------------ # generate HTML for index and all pages @@ -27,16 +29,30 @@ def cli(ctx, opt_graph_path, opt_output_dir): print(f"Not a graph: {opt_graph_path}") return - print(f"Output site to {opt_output_dir}") + # build everything here + graph_dir = join(opt_output_dir, graph.path) + # load site index + index_html = load_text(join(app_cfg.DIR_STATIC, 'site.html'), split=False) + index_html = index_html.replace('SITE_PATH', '/' + graph.path) + + # write site JSON data site_data = { 'graph': sanitize_graph(graph.toSiteJSON()) } + write_json(site_data, join(graph_dir, 'index.json'), default=str) - index_html = load_text(join(app_cfg.DIR_STATIC, 'site.html'), split=False) - write_json(site_data, join(opt_output_dir, graph.path, 'index.json'), default=str) - # write_index(graph, None, index_html, join(opt_output_dir, graph.path, 'index.html')) + # import custom css + site_css = load_text(join(app_cfg.DIR_STATIC, 'site.css'), split=False) + site_css = site_css.replace('SITE_PATH', '/' + graph.path) + write_text(site_css, join(graph_dir, 'site.css')) + copy_tree(join(app_cfg.DIR_STATIC, 'fonts'), join(graph_dir, 'static/fonts')) + copy_tree(join(app_cfg.DIR_STATIC, 'img'), join(graph_dir, 'static/img')) + # write index file, redirects to homepage home_page = site_data['graph']['home_page'] - write_text(f'<meta http-equiv="refresh" content="0; url={home_page}">', join(opt_output_dir, graph.path, 'index.html')) + if home_page is None: + print("Homepage not set! Shift-click a page on the graph to make it the homepage.") + return + write_text(f'<meta http-equiv="refresh" content="0; url={home_page}">', join(graph_dir, 'index.html')) index_path = "" for page in graph.pages: @@ -46,12 +62,18 @@ def cli(ctx, opt_graph_path, opt_output_dir): print(f'/{page_path} [index]') else: print(f'/{page_path}') - write_index(graph, page, index_html, join(opt_output_dir, graph.path, page.path, 'index.html')) + write_index(graph, page, index_html, join(graph_dir, page.path, 'index.html')) # ------------------------------------------------ - # generate javascript... + # build javascript + + print("Building javascript...") + print(f'NODE_ENV=production webpack --config ./webpack.config.site.js -o {graph_dir}/bundle.js') + os.chdir(app_cfg.DIR_PROJECT_ROOT) + os.system(f'NODE_ENV=production webpack --config ./webpack.config.site.js -o {graph_dir}/bundle.js') - # NODE_ENV=production webpack --config ./webpack.config.site.js -o ./data_store/exports/asdf/bundle.js + print("Site export complete!") + print(f"Graph exported to: {graph_dir}") def write_index(graph, page, index_html, fp_out): if page is None: diff --git a/frontend/common/index.js b/frontend/common/index.js index 3647203..5c0dc50 100644 --- a/frontend/common/index.js +++ b/frontend/common/index.js @@ -8,9 +8,10 @@ export { LabelDescription, ColorInput, } from './form.component' export { - Loader, Swatch, Dot, Columns, Statistic, Detections, Progress + Swatch, Dot, Columns, Statistic, Detections, Progress } from './miscellaneous.component' export { default as TableIndex } from './tableIndex.component' +export { Loader } from './loader.component' export { TableObject, TableArray, TableTuples, TableRow, TableCell diff --git a/frontend/common/loader.component.js b/frontend/common/loader.component.js new file mode 100644 index 0000000..f0a0c69 --- /dev/null +++ b/frontend/common/loader.component.js @@ -0,0 +1,16 @@ +import React, { Component } from 'react'; + +import './loader.css' + +const Loader = () => ( + <div> + <div className='circular-loader color'> + <div className="stroke"> + <div className="stroke-left"></div> + <div className="stroke-right"></div> + </div> + </div> + </div> +) + +export { Loader } diff --git a/frontend/common/miscellaneous.component.js b/frontend/common/miscellaneous.component.js index 4eb23f1..cf12ef5 100644 --- a/frontend/common/miscellaneous.component.js +++ b/frontend/common/miscellaneous.component.js @@ -2,17 +2,6 @@ import React, { Component } from 'react'; import { Link } from 'react-router-dom' import { clamp, percent } from '../util' -export const Loader = () => ( - <div> - <div className='circular-loader color'> - <div className="stroke"> - <div className="stroke-left"></div> - <div className="stroke-right"></div> - </div> - </div> - </div> -) - export const Swatch = ({ color }) => ( <div className='swatch' diff --git a/frontend/site/site/site.actions.js b/frontend/site/site/site.actions.js index 2362e5f..5724df8 100644 --- a/frontend/site/site/site.actions.js +++ b/frontend/site/site/site.actions.js @@ -11,14 +11,14 @@ export const setSiteTitle = title => dispatch => { export const loadSite = (graph_name, path_name) => dispatch => ( api(dispatch, types.site, 'site', '/' + graph_name + '/index.json') - .then(res => { - const { graph } = res.data - // console.log(graph) - // console.log(graph.home_page) - const first_path = ["", graph_name, path_name].join("/") - if (!path_name || !(first_path in graph.pages)) { - // console.log(graph.home_page) - window.location.href = graph.home_page - } - }) + // .then(res => { + // const { graph } = res.data + // // console.log(graph) + // // console.log(graph.home_page) + // const first_path = ["", graph_name, path_name].join("/") + // if (!path_name || !(first_path in graph.pages)) { + // // console.log(graph.home_page) + // window.location.href = graph.home_page + // } + // }) ) diff --git a/frontend/site/viewer/viewer.container.js b/frontend/site/viewer/viewer.container.js index 68088d2..da81551 100644 --- a/frontend/site/viewer/viewer.container.js +++ b/frontend/site/viewer/viewer.container.js @@ -4,7 +4,7 @@ import { bindActionCreators } from 'redux' import { connect } from 'react-redux' import actions from '../actions' -import { Loader } from '../../common' +import { Loader } from '../../common/loader.component' import TileHandle from '../../views/page/components/tile.handle' import '../../views/page/page.css' diff --git a/frontend/views/page/components/tile.handle.js b/frontend/views/page/components/tile.handle.js index f3a700b..bd47ae9 100644 --- a/frontend/views/page/components/tile.handle.js +++ b/frontend/views/page/components/tile.handle.js @@ -11,7 +11,7 @@ const TileHandle = ({ tile, bounds, box, viewing, onMouseDown, onDoubleClick }) // console.log(generateTransform(tile)) let content; let className = ['tile', tile.type].join(' ') - if (tile.target_page_id) { + if (tile.target_page_id || (viewing && tile.href)) { className += ' ' + (tile.settings.cursor || 'hand_up') } // console.log(tile.settings) diff --git a/frontend/views/page/cursors.css b/frontend/views/page/cursors.css new file mode 100644 index 0000000..5f90dd1 --- /dev/null +++ b/frontend/views/page/cursors.css @@ -0,0 +1,15 @@ +/* cursors */ +/* keep in separate file so they don't conflict. a copy of this lives in site.css */ + +.tile.hand_up { + cursor: url(/static/img/hand_up.png) 40 10, pointer; +} +.tile.hand_right { + cursor: url(/static/img/hand_right.png) 90 40, pointer; +} +.tile.hand_down { + cursor: url(/static/img/hand_down.png) 60 90, pointer; +} +.tile.hand_left { + cursor: url(/static/img/hand_left.png) 10 60, pointer; +} diff --git a/frontend/views/page/page.container.js b/frontend/views/page/page.container.js index 5da41d6..26bed30 100644 --- a/frontend/views/page/page.container.js +++ b/frontend/views/page/page.container.js @@ -4,6 +4,7 @@ import { bindActionCreators } from 'redux' import { connect } from 'react-redux' import './page.css' +import './cursors.css' import actions from '../../actions' import { Loader } from '../../common' diff --git a/frontend/views/page/page.css b/frontend/views/page/page.css index c29aff2..ec41241 100644 --- a/frontend/views/page/page.css +++ b/frontend/views/page/page.css @@ -168,18 +168,3 @@ width: 6rem; max-width: 6rem; } - -/* cursors */ - -.tile.hand_up { - cursor: url(/static/img/hand_up.png) 40 10, pointer; -} -.tile.hand_right { - cursor: url(/static/img/hand_right.png) 90 40, pointer; -} -.tile.hand_down { - cursor: url(/static/img/hand_down.png) 60 90, pointer; -} -.tile.hand_left { - cursor: url(/static/img/hand_left.png) 10 60, pointer; -} diff --git a/static/site.css b/static/site.css new file mode 100644 index 0000000..7f4a733 --- /dev/null +++ b/static/site.css @@ -0,0 +1,129 @@ + +* { box-sizing: border-box; } +html, body { + margin: 0; + padding: 0; + width: 100%; + height: 100%; +} +body { + background: #000; + color: #ddd; + overflow: hidden; + font-family: 'Roboto', sans-serif; + font-size: 0.875rem; + height: 100%; + width: 100%; +} +.gray { + color: #888; +} + +/* layout */ + +.container { + height: 100%; + width: 100%; +} +.app { + /*display: flex;*/ + height: 100%; + width: 100%; +} +.app > div { + display: flex; + flex-direction: column; + height: 100%; + width: 100%; +} +.app .body { + display: flex; + flex-direction: column; + flex-grow: 1; + position: relative; + height: 100%; + width: 100%; +} + +.row { + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: flex-start; +} +.row > div { + margin-right: 1.5rem; +} +.row > div:last-child { + margin-right: 0; +} + +@font-face { + font-family: 'Roboto'; + src: url('SITE_PATH/static/fonts/Roboto-Bold.ttf') format('truetype'); + font-weight: bold; +} +@font-face { + font-family: 'Roboto'; + src: url('SITE_PATH/static/fonts/Roboto-BoldItalic.ttf') format('truetype'); + font-weight: bold; + font-style: italic; +} +/* +@font-face { + font-family: 'Roboto'; + src: url('SITE_PATH/static/fonts/Roboto-Light.ttf') format('truetype'); + font-weight: 100; +} +@font-face { + font-family: 'Roboto'; + src: url('SITE_PATH/static/fonts/Roboto-LightItalic.ttf') format('truetype'); + font-weight: 100; +} +*/ +@font-face { + font-family: 'Roboto'; + src: url('SITE_PATH/static/fonts/Roboto-Medium.ttf') format('truetype'); + font-weight: 300; +} +@font-face { + font-family: 'Roboto'; + src: url('SITE_PATH/static/fonts/Roboto-MediumItalic.ttf') format('truetype'); + font-style: italic; + font-weight: 300; +} +@font-face { + font-family: 'Roboto'; + src: url('SITE_PATH/static/fonts/Roboto-Regular.ttf') format('truetype'); +} +@font-face { + font-family: 'Roboto'; + src: url('SITE_PATH/static/fonts/Roboto-Italic.ttf') format('truetype'); + font-style: italic; +} +/* +@font-face { + font-family: 'Roboto'; + src: url('SITE_PATH/static/fonts/Roboto-Thin.ttf') format('truetype'); + font-weight: 100; +} +@font-face { + font-family: 'Roboto'; + src: url('SITE_PATH/static/fonts/Roboto-ThinItalic.ttf') format('truetype'); + font-weight: 100; +} +*/ + + +.tile.hand_up { + cursor: url(SITE_PATH/static/img/hand_up.png) 40 10, pointer; +} +.tile.hand_right { + cursor: url(SITE_PATH/static/img/hand_right.png) 90 40, pointer; +} +.tile.hand_down { + cursor: url(SITE_PATH/static/img/hand_down.png) 60 90, pointer; +} +.tile.hand_left { + cursor: url(SITE_PATH/static/img/hand_left.png) 10 60, pointer; +} diff --git a/static/site.html b/static/site.html index 18bd0d0..e19847b 100644 --- a/static/site.html +++ b/static/site.html @@ -4,6 +4,7 @@ <meta charset="UTF-8"> <title>PAGE_TITLE</title> <meta name="viewport" content="width=device-width,initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="SITE_PATH/site.css" /> <style> html { background: #000; } </style> diff --git a/webpack.config.prod.js b/webpack.config.prod.js index b57c765..6e9f404 100644 --- a/webpack.config.prod.js +++ b/webpack.config.prod.js @@ -18,8 +18,9 @@ module.exports = { plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify("production"), - 'process.env.S3_HOST': JSON.stringify(process.env.S3_HOST || ""), - 'process.env.API_HOST': JSON.stringify(process.env.API_HOST || ""), + // 'process.env.S3_HOST': JSON.stringify(process.env.S3_HOST || ""), + // 'process.env.API_HOST': JSON.stringify(process.env.API_HOST || ""), + '__REACT_DEVTOOLS_GLOBAL_HOOK__': '({ isDisabled: true })' }), new TerserPlugin(), new webpack.optimize.AggressiveMergingPlugin(), diff --git a/webpack.config.site.js b/webpack.config.site.js index 8a62c75..07a48c8 100644 --- a/webpack.config.site.js +++ b/webpack.config.site.js @@ -2,12 +2,12 @@ require('dotenv').config() const webpack = require('webpack') const path = require('path') +const TerserPlugin = require('terser-webpack-plugin') + -// print stack-trace of deprecations in webpack plugins, if something causes this -// process.traceDeprecation = true module.exports = { - mode: "development", + mode: "production", entry: { main: './frontend/site/index.js' }, @@ -15,7 +15,29 @@ module.exports = { path: path.resolve(__dirname, 'static/js/dist'), filename: 'bundle.js' }, - devtool: 'cheap-module-eval-source-map', + plugins: [ + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify("production"), + // 'process.env.S3_HOST': JSON.stringify(process.env.S3_HOST || ""), + // 'process.env.API_HOST': JSON.stringify(process.env.API_HOST || ""), + '__REACT_DEVTOOLS_GLOBAL_HOOK__': '({ isDisabled: true })' + }), + new TerserPlugin(), + new webpack.optimize.AggressiveMergingPlugin(), + // new Visualizer({ + // filename: './statistics.html' + // }) + ], + optimization: { + minimize: true, + minimizer: [new TerserPlugin({ + terserOptions: { + compress: { + // drop_console: true, + } + } + })], + }, resolve: { alias: { // "react": "preact/compat", @@ -23,12 +45,7 @@ module.exports = { // "react-dom": "preact/compat", } }, - plugins: [ - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': '"development"', - '__REACT_DEVTOOLS_GLOBAL_HOOK__': '({ isDisabled: true })' - }), - ], + devtool: 'cheap-module-source-map', module: { rules: [ { @@ -39,16 +56,14 @@ module.exports = { test: /\.js$/, // include: path.resolve(__dirname, 'client'), exclude: /(node_modules|bower_components|build)/, - use: { - loader: 'babel-loader', - options: { - presets: ['@babel/preset-env'], - plugins: [ - "@babel/plugin-transform-runtime", - ], - } + loader: 'babel-loader', + options: { + presets: ['@babel/preset-react'], + plugins: [ + "@babel/plugin-transform-runtime", + ], } } ] - } -} + }, +}; |
