diff --git a/packages/web/babel.config.js b/packages/web/babel.config.js index 760c7d321..fb437a2f9 100644 --- a/packages/web/babel.config.js +++ b/packages/web/babel.config.js @@ -28,11 +28,20 @@ module.exports = (api) => { }, // 'transform-runtime': {}, // 'styled-jsx': {}, - // 'class-properties': {}, + // 'class-properties': { loose: true }, + // 'preset-typescript': { + // onlyRemoveTypeImports: true, + // }, }, ], ], plugins: [ + ['@babel/plugin-proposal-decorators', { legacy: true }], + ['@babel/plugin-proposal-class-properties', { loose: true }], + 'babel-plugin-parameter-decorator', + // ['@babel/plugin-proposal-decorators', { legacy: true }], + // '@babel/plugin-proposal-class-properties', + // 'babel-plugin-transform-typescript-metadata', '@babel/plugin-proposal-numeric-separator', 'babel-plugin-styled-components', 'babel-plugin-lodash', @@ -49,7 +58,8 @@ module.exports = (api) => { root: [moduleRoot], removeImport: false, alias: { - src: path.join(moduleRoot, 'src'), + 'src': path.join(moduleRoot, 'src'), + '@extensions': moduleRoot, }, }, ], diff --git a/packages/web/config/next/next.config.ts b/packages/web/config/next/next.config.ts index 20cab8012..0a3a99307 100644 --- a/packages/web/config/next/next.config.ts +++ b/packages/web/config/next/next.config.ts @@ -1,5 +1,7 @@ import path from 'path' +import { uniq } from 'lodash' + import type { NextConfig } from 'next' import getWithMDX from '@next/mdx' // import withBundleAnalyzer from '@zeit/next-bundle-analyzer' @@ -24,6 +26,7 @@ import withRaw from './withRaw' import withSvg from './withSvg' import withImages from './withImages' import withThreads from './withThreads' +import withoutNpmCss from './withoutNpmCss' // import withoutMinification from './withoutMinification' const { @@ -109,22 +112,28 @@ const withTypeChecking = getWithTypeChecking({ memoryLimit: 2048, }) -const withTranspileModules = getWithTranspileModules([ +const transpilationListDev = [ + // prettier-ignore + 'auspice', + 'd3-scale', +] + +const transpilationListProd = uniq([ + ...transpilationListDev, '!d3-array/src/cumsum.js', '@loadable', 'create-color', 'd3-array', - 'd3-scale', 'debug', 'delay', 'immer', + 'is-observable', 'lodash', 'observable-fns', 'p-min-delay', 'proper-url-join', 'query-string', 'react-router', - 'is-observable', 'react-share', 'recharts', 'redux-saga', @@ -135,8 +144,11 @@ const withTranspileModules = getWithTranspileModules([ 'threads', ]) +const withTranspileModules = getWithTranspileModules(PRODUCTION ? transpilationListProd : transpilationListDev) + const config = withPlugins( [ + [withoutNpmCss], [withEnvironment], [withExtraWatch], [withThreads], @@ -148,7 +160,7 @@ const config = withPlugins( [withMDX, { pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'md', 'mdx'] }], [withLodash], [withTypeChecking], - PRODUCTION && [withTranspileModules], + [withTranspileModules], PRODUCTION && [withStaticComprression], // [withoutMinification], ].filter(Boolean), diff --git a/packages/web/config/next/withoutNpmCss.ts b/packages/web/config/next/withoutNpmCss.ts new file mode 100644 index 000000000..4bf82713a --- /dev/null +++ b/packages/web/config/next/withoutNpmCss.ts @@ -0,0 +1,30 @@ +import webpack from 'webpack' +import type { NextConfig } from 'next' + +import { addWebpackPlugin } from './lib/addWebpackPlugin' + +export default function withoutNpmCss(nextConfig: NextConfig) { + let nextConfigNew = nextConfig + nextConfigNew = addWebpackPlugin( + nextConfigNew, + + new webpack.ContextReplacementPlugin(/.*/, (context) => { + console.log({ context }) + }), + ) + + nextConfigNew = addWebpackPlugin( + nextConfigNew, + new webpack.IgnorePlugin({ + checkResource: (resource: string) => { + return ( + resource.endsWith('awesomplete.css') || + resource.includes('core-js/library') || + resource.includes('babel-runtime') + ) + }, + }), + ) + + return nextConfigNew +} diff --git a/packages/web/package.json b/packages/web/package.json index 4872b34d2..94470243f 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -61,6 +61,7 @@ "@types/react-virtualized-auto-sizer": "1.0.0", "@types/react-window": "1.8.2", "animate.css": "4.1.0", + "auspice": "2.17.3", "autoprefixer": "9.8.5", "axios": "0.19.2", "bootstrap": "4.5.0", @@ -95,6 +96,7 @@ "react-i18next": "11.7.0", "react-icons": "3.10.0", "react-if": "3.4.3", + "react-no-ssr": "1.1.0", "react-redux": "7.2.0", "react-resize-detector": "5.0.6", "react-virtualized-auto-sizer": "1.0.2", @@ -105,6 +107,7 @@ "redux-persist": "6.0.0", "redux-saga": "1.1.3", "redux-saga-test-plan": "4.0.0-rc.3", + "reflect-metadata": "0.1.13", "regenerator-runtime": "0.13.5", "reselect": "4.0.0", "semver": "7.3.2", @@ -120,15 +123,21 @@ "devDependencies": { "@babel/core": "7.10.4", "@babel/node": "7.10.4", + "@babel/plugin-proposal-class-properties": "7.10.4", + "@babel/plugin-proposal-decorators": "7.10.4", "@babel/plugin-proposal-numeric-separator": "7.10.4", + "@babel/plugin-syntax-dynamic-import": "7.8.3", "@babel/plugin-transform-flow-strip-types": "7.10.4", "@babel/plugin-transform-modules-commonjs": "7.10.4", "@babel/plugin-transform-react-constant-elements": "7.10.4", "@babel/plugin-transform-react-inline-elements": "7.10.4", "@babel/plugin-transform-runtime": "7.10.4", + "@babel/preset-env": "7.10.4", + "@babel/preset-react": "7.10.4", "@babel/register": "7.10.4", "@babel/runtime": "7.10.4", "@babel/runtime-corejs3": "7.10.4", + "@extensions": "link:3rdparty/__empty-module", "@next/mdx": "9.4.4", "@nuxt/friendly-errors-webpack-plugin": "2.5.0", "@packtracker/webpack-plugin": "2.3.0", @@ -158,6 +167,7 @@ "@types/react": "16.9.43", "@types/react-dom": "16.9.8", "@types/react-helmet": "6.0.0", + "@types/react-no-ssr": "1.1.1", "@types/react-redux": "7.1.9", "@types/react-resize-detector": "4.2.0", "@types/react-router": "5.1.8", @@ -179,10 +189,12 @@ "babel-jest": "26.1.0", "babel-plugin-lodash": "3.3.4", "babel-plugin-module-resolver": "4.0.0", + "babel-plugin-parameter-decorator": "1.0.16", "babel-plugin-redux-saga": "1.1.2", "babel-plugin-smart-webpack-import": "1.7.0", "babel-plugin-styled-components": "1.10.7", "babel-plugin-transform-react-remove-prop-types": "0.4.24", + "babel-plugin-transform-typescript-metadata": "0.3.0", "babel-plugin-typescript-to-proptypes": "1.3.2", "codecov": "3.7.0", "compression-webpack-plugin": "4.0.0", @@ -291,10 +303,43 @@ "yaml-loader": "0.6.0" }, "resolutions": { + "@babel/core": "7.10.4", + "@babel/node": "7.10.4", + "@babel/plugin-proposal-class-properties": "7.10.4", + "@babel/plugin-proposal-decorators": "7.10.4", + "@babel/plugin-proposal-numeric-separator": "7.10.4", + "@babel/plugin-syntax-dynamic-import": "7.8.3", + "@babel/plugin-transform-flow-strip-types": "7.10.4", + "@babel/plugin-transform-modules-commonjs": "7.10.4", + "@babel/plugin-transform-react-constant-elements": "7.10.4", + "@babel/plugin-transform-react-inline-elements": "7.10.4", + "@babel/plugin-transform-runtime": "7.10.4", + "@babel/preset-env": "7.10.4", + "@babel/preset-react": "7.10.4", + "@babel/register": "7.10.4", + "@babel/runtime": "7.10.4", + "@babel/runtime-corejs3": "7.10.4", + "@extensions": "link:3rdparty/__empty-module", + "babel-jest": "26.1.0", + "babel-plugin-lodash": "3.3.4", + "babel-plugin-module-resolver": "4.0.0", + "babel-plugin-redux-saga": "1.1.2", + "babel-plugin-smart-webpack-import": "1.7.0", + "babel-plugin-styled-components": "1.10.7", + "babel-plugin-transform-react-remove-prop-types": "0.4.24", + "babel-plugin-transform-typescript-metadata": "0.3.0", + "babel-plugin-typescript-to-proptypes": "1.3.2", "core-js": "3.6.5", "lodash": "4.17.19", "moment": "2.27.0", + "react": "16.13.1", + "react-dom": "16.13.1", + "react-error-boundary": "2.2.3", + "react-redux": "7.2.0", + "redux": "4.0.5", + "reflect-metadata": "0.1.13", "styled-components": "5.1.1", - "svgo": "1.3.2" + "svgo": "1.3.2", + "webpack": "4.43.0" } } diff --git a/packages/web/src/components/Auspice/AuspicePage.tsx b/packages/web/src/components/Auspice/AuspicePage.tsx new file mode 100644 index 000000000..8b00180f6 --- /dev/null +++ b/packages/web/src/components/Auspice/AuspicePage.tsx @@ -0,0 +1,268 @@ +// import React from 'react' +// +// // import { connect } from 'react-redux' +// // import { State } from 'state/reducer' +// +// import AuspiceMain from 'auspice/src/components/main/index' +// +// // export interface Props { +// // foo: boolean +// // } +// // +// // const mapStateToProps = (state: State) => ({ foo: state.ui.filterPanelCollapsed }) +// // +// // @connect(mapStateToProps) +// // class AuspicePage extends React.Component { +// // public constructor(props: Props) { +// // super(props) +// // } +// // +// // render() { +// // console.log({ foo: this.props.foo }) +// // return null +// // } +// // } +// +// function AuspicePage() { +// return +// } +// +// export { AuspicePage } + +import React from 'react' +// import PropTypes from 'prop-types' +// import NoSSR from 'react-no-ssr' +import { ThemeProvider } from 'styled-components' +import SidebarToggle from 'auspice/src/components/framework/sidebar-toggle' +// import { controlsHiddenWidth } from 'auspice/src/util/globals' +import DownloadModal from 'auspice/src/components/download/downloadModal' +// import { analyticsNewPage } from 'auspice/src/util/googleAnalytics' +// import handleFilesDropped from 'auspice/src/actions/filesDropped' +import { TOGGLE_SIDEBAR } from 'auspice/src/actions/types' +import AnimationController from 'auspice/src/components/framework/animationController' +import { Sidebar } from 'auspice/src/components/main/sidebar' +import { calcPanelDims, calcStyles } from 'auspice/src/components/main/utils' +import { PanelsContainer, sidebarTheme } from 'auspice/src/components/main/styles' +import ErrorBoundary from 'auspice/src/util/errorBoundry' +import Tree from 'auspice/src/components/tree' + +// import Spinner from 'auspice/src/components/framework/spinner' +// import MobileNarrativeDisplay from 'auspice/src/components/narrative/MobileNarrativeDisplay' + +// const Entropy = lazy(() => import('auspice/src/components/entropy')) +// const Frequencies = lazy(() => import('auspice/src/components/frequencies')) + +// NOTE: Disable server-side rendering for Tree component. +// Some of the subcomponents there rely on `document` global to be present, however it is not available during server rendering. +// import dynamic from 'next/dynamic' +// const Tree = dynamic(() => import('auspice/src/components/tree'), { ssr: false }) + +// @connect((state) => ({ +// panelsToDisplay: state.controls.panelsToDisplay, +// panelLayout: state.controls.panelLayout, +// displayNarrative: state.narrative.display, +// narrativeIsLoaded: state.narrative.loaded, +// narrativeTitle: state.narrative.title, +// browserDimensions: state.browserDimensions.browserDimensions, +// frequenciesLoaded: state.frequencies.loaded, +// metadataLoaded: state.metadata.loaded, +// treeLoaded: state.tree.loaded, +// sidebarOpen: state.controls.sidebarOpen, +// showOnlyPanels: state.controls.showOnlyPanels +// })) +class Main extends React.Component { + constructor(props) { + super(props) + // /* window listner employed to toggle switch to mobile display. + // NOTE: this used to toggle sidebar open boolean when that was stored + // as state here, but his has since ben moved to redux state. The mobile + // display should likewise be lifted to redux state */ + // const mql = window.matchMedia(`(min-width: ${controlsHiddenWidth}px)`) + // mql.addListener(() => + // this.setState({ + // mobileDisplay: !this.state.mql.matches, + // }), + // ) + // this.state = { + // mql, + // mobileDisplay: !mql.matches, + // showSpinner: !(this.props.metadataLoaded && this.props.treeLoaded), + // } + // analyticsNewPage() + this.toggleSidebar = this.toggleSidebar.bind(this) + } + + // static propTypes = { + // dispatch: PropTypes.func.isRequired, + // } + + // componentWillReceiveProps(nextProps) { + // if (this.state.showSpinner && nextProps.metadataLoaded && nextProps.treeLoaded) { + // this.setState({ showSpinner: false }) + // } + // } + + // componentDidMount() { + // document.addEventListener( + // 'dragover', + // (e) => { + // e.preventDefault() + // }, + // false, + // ) + // document.addEventListener( + // 'drop', + // (e) => { + // e.preventDefault() + // return this.props.dispatch(handleFilesDropped(e.dataTransfer.files)) + // }, + // false, + // ) + // } + + toggleSidebar() { + this.props.dispatch({ type: TOGGLE_SIDEBAR, value: !this.props.sidebarOpen }) + } + + shouldShowMapLegend() { + const showingTree = this.props.panelsToDisplay.includes('tree') + const inGrid = this.props.panelLayout !== 'grid' + + return !showingTree || inGrid + } + + render() { + // if (this.state.showSpinner) { + // return + // } + + /* for mobile narratives we use a custom component as the nesting of view components is different */ + /* TODO - the breakpoint for `mobileDisplay` needs testing */ + const { + panelsToDisplay, + displayNarrative, + dispatch, + browserDimensions, + narrativeTitle, + panelLayout, + sidebarOpen, + } = this.props + + // if (this.state.mobileDisplay && displayNarrative) { + // return ( + // <> + // + // + // + // + // + // ) + // } + + /* The following code is employed for: + * (a) all non-narrative displays (including on mobile) + * (b) narrative display for non-mobile (i.e. display side-by-side) + */ + const { availableWidth, availableHeight, sidebarWidth, overlayStyles } = calcStyles( + browserDimensions, + displayNarrative, + sidebarOpen, + // this.state.mobileDisplay, + ) + + // const overlayHandler = () => { + // dispatch({ type: TOGGLE_SIDEBAR, value: false }) + // } + + const { big, chart } = calcPanelDims( + panelLayout === 'grid', + panelsToDisplay, + displayNarrative, + availableWidth, + availableHeight, + ) + + return ( + + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + + {/* {this.props.narrativeIsLoaded && !this.props.panelsToDisplay.includes('EXPERIMENTAL_MainDisplayMarkdown') */} + {/* ? renderNarrativeToggle(this.props.dispatch, this.props.displayNarrative) */} + {/* : null} */} + + {/* {this.props.displayNarrative || this.props.showOnlyPanels ? null : ( */} + {/* */} + {/* )} */} + + + + {/* {this.props.panelsToDisplay.includes('tree') ? : null} */} + + {/* {this.props.panelsToDisplay.includes('map') ? ( */} + {/* */} + {/* ) : null} */} + + {/* {this.props.panelsToDisplay.includes('entropy') ? ( */} + {/* */} + {/* */} + {/* */} + {/* ) : null} */} + + {/* {this.props.panelsToDisplay.includes('frequencies') && this.props.frequenciesLoaded ? ( */} + {/* */} + {/* */} + {/* */} + {/* ) : null} */} + + {/* {this.props.displayNarrative || this.props.showOnlyPanels ? null : ( */} + {/*