diff --git a/console/.eslintrc b/console/.eslintrc index 5cc689831d9..7c25d02c336 100644 --- a/console/.eslintrc +++ b/console/.eslintrc @@ -100,6 +100,7 @@ "__DISABLE_SSR__": true, "__DEVTOOLS__": true, "socket": true, - "webpackIsomorphicTools": true + "webpackIsomorphicTools": true, + "CONSOLE_ASSET_VERSION": true } } diff --git a/console/src/Globals.js b/console/src/Globals.js index 09d192d07de..e13db418d8d 100644 --- a/console/src/Globals.js +++ b/console/src/Globals.js @@ -44,6 +44,7 @@ const globals = { window.__env.nodeEnv !== 'development' ? 'console' : 'console_test', assetsPath: window.__env.assetsPath, serverVersion: window.__env.serverVersion, + consoleAssetVersion: CONSOLE_ASSET_VERSION, featuresCompatibility: window.__env.serverVersion ? getFeaturesCompatibility(window.__env.serverVersion) : null, @@ -57,6 +58,7 @@ if (!window.__env.urlPrefix) { if (!window.__env.consoleMode) { globals.consoleMode = SERVER_CONSOLE_MODE; } + if (!globals.adminSecret) { globals.adminSecret = null; } diff --git a/console/src/components/Main/Main.js b/console/src/components/Main/Main.js index 219266253c2..ad06d21da5c 100644 --- a/console/src/components/Main/Main.js +++ b/console/src/components/Main/Main.js @@ -162,7 +162,8 @@ class Main extends React.Component { const github = require('./images/Github.svg'); const discord = require('./images/Discord.svg'); const mail = require('./images/mail.svg'); - const docs = require('./images/logo.svg'); + const docs = require('./images/docs-logo.svg'); + const about = require('./images/console-logo.svg'); const pixHeart = require('./images/pix-heart.svg'); const currentLocation = location.pathname; @@ -604,6 +605,16 @@ class Main extends React.Component { Head to docs +
  • + + {'about'} + About + +
  • diff --git a/console/src/components/Main/images/console-logo.svg b/console/src/components/Main/images/console-logo.svg new file mode 100644 index 00000000000..bb10f579bc3 --- /dev/null +++ b/console/src/components/Main/images/console-logo.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/console/src/components/Main/images/docs-logo.svg b/console/src/components/Main/images/docs-logo.svg new file mode 100644 index 00000000000..cf763b2fff3 --- /dev/null +++ b/console/src/components/Main/images/docs-logo.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/console/src/components/Main/images/logo.svg b/console/src/components/Main/images/logo.svg deleted file mode 100644 index 1caa11fa86a..00000000000 --- a/console/src/components/Main/images/logo.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/console/src/components/Services/About/About.js b/console/src/components/Services/About/About.js new file mode 100644 index 00000000000..1316225afac --- /dev/null +++ b/console/src/components/Services/About/About.js @@ -0,0 +1,143 @@ +import React, { Component } from 'react'; + +import Endpoints from '../../../Endpoints'; + +import globals from '../../../Globals'; + +import styles from './About.scss'; + +class About extends Component { + state = { + serverVersion: null, + latestServerVersion: null, + consoleAssetVersion: globals.consoleAssetVersion, + }; + + componentDidMount() { + fetch(Endpoints.version) + .then(response => response.json()) + .then(serverVersion => + this.setState({ + serverVersion: serverVersion.version, + }) + ); + + fetch(Endpoints.updateCheck) + .then(response => response.json()) + .then(latest => + this.setState({ + latestServerVersion: latest.latest, + }) + ); + } + + render() { + const { + serverVersion, + latestServerVersion, + consoleAssetVersion, + } = this.state; + + const spinner = ; + + const getServerVersionSection = () => { + return ( +
    + Server version: + + {serverVersion || spinner} + +
    + ); + }; + + const getLatestServerVersionSection = () => { + let updateLinks; + if ( + serverVersion && + latestServerVersion && + serverVersion !== latestServerVersion + ) { + updateLinks = ( + + + + View Changelog + + + +  ·  + + + + Update Now + + + + ); + } + + return ( +
    + Latest server version: + + {latestServerVersion || spinner} {updateLinks} + +
    + ); + }; + + const getConsoleAssetVersionSection = () => { + return ( +
    + Console asset version: + + {consoleAssetVersion || 'NA'} + +
    + ); + }; + + return ( +
    +
    +

    + About +

    +
    +
    + {getServerVersionSection()} +
    +
    + {getLatestServerVersionSection()} +
    +
    + {getConsoleAssetVersionSection()} +
    +
    +
    +
    + ); + } +} + +const mapStateToProps = () => { + return {}; +}; + +const aboutConnector = connect => connect(mapStateToProps)(About); + +export default aboutConnector; diff --git a/console/src/components/Services/About/About.scss b/console/src/components/Services/About/About.scss new file mode 100644 index 00000000000..cf1e3d14855 --- /dev/null +++ b/console/src/components/Services/About/About.scss @@ -0,0 +1,3 @@ +@import "../../Common/Common.scss"; + + diff --git a/console/src/components/Services/Data/TablePermissions/PermissionBuilder/PermissionBuilder.js b/console/src/components/Services/Data/TablePermissions/PermissionBuilder/PermissionBuilder.js index 830be2eb418..6f278ec060d 100644 --- a/console/src/components/Services/Data/TablePermissions/PermissionBuilder/PermissionBuilder.js +++ b/console/src/components/Services/Data/TablePermissions/PermissionBuilder/PermissionBuilder.js @@ -455,7 +455,9 @@ class PermissionBuilder extends React.Component { input = inputBox(); suggestion = jsonSuggestion(); } else if (valueType === 'column') { - input = renderSelect(dispatchInput, value, tableColumns); + input = wrapDoubleQuotes( + renderSelect(dispatchInput, value, tableColumns) + ); } else { input = wrapDoubleQuotes(inputBox()); suggestion = sessionVariableSuggestion(); diff --git a/console/src/components/Services/Metadata/Sidebar.js b/console/src/components/Services/Metadata/Sidebar.js index 277e811a60c..58eb8a630a4 100644 --- a/console/src/components/Services/Metadata/Sidebar.js +++ b/console/src/components/Services/Metadata/Sidebar.js @@ -33,7 +33,7 @@ const Sidebar = ({ location, metadata }) => { sectionsData.push({ key: 'allowed-queries', link: '/metadata/allowed-queries', - dataTestVal: 'metadata-allowed-queries-link', + dataTestVal: 'allowed-queries-link', title: 'Allowed Queries', }); diff --git a/console/src/components/VoyagerView/VoyagerView.js b/console/src/components/Services/VoyagerView/VoyagerView.js similarity index 89% rename from console/src/components/VoyagerView/VoyagerView.js rename to console/src/components/Services/VoyagerView/VoyagerView.js index b7d4356f981..f3aee36a9d9 100644 --- a/console/src/components/VoyagerView/VoyagerView.js +++ b/console/src/components/Services/VoyagerView/VoyagerView.js @@ -1,8 +1,8 @@ import React, { Component } from 'react'; import { GraphQLVoyager } from 'graphql-voyager'; import fetch from 'isomorphic-fetch'; -import Endpoints from '../../Endpoints'; -import '../../../node_modules/graphql-voyager/dist/voyager.css'; +import Endpoints from '../../../Endpoints'; +import '../../../../node_modules/graphql-voyager/dist/voyager.css'; import './voyagerView.css'; class VoyagerView extends Component { diff --git a/console/src/components/VoyagerView/voyagerView.css b/console/src/components/Services/VoyagerView/voyagerView.css similarity index 100% rename from console/src/components/VoyagerView/voyagerView.css rename to console/src/components/Services/VoyagerView/voyagerView.css diff --git a/console/src/routes.js b/console/src/routes.js index 293dbc17bc9..ab4393aceaa 100644 --- a/console/src/routes.js +++ b/console/src/routes.js @@ -21,9 +21,11 @@ import { getCustomResolverRouter } from './components/Services/CustomResolver'; import generatedApiExplorer from './components/Services/ApiExplorer/ApiExplorerGenerator'; -import generatedLoginConnector from './components/Login/Login'; +import generatedVoyagerConnector from './components/Services/VoyagerView/VoyagerView'; -import generatedVoyagerConnector from './components/VoyagerView/VoyagerView'; +import about from './components/Services/About/About'; + +import generatedLoginConnector from './components/Login/Login'; import metadataContainer from './components/Services/Metadata/Container'; import metadataOptionsContainer from './components/Services/Metadata/MetadataOptions/MetadataOptions'; @@ -91,14 +93,15 @@ const routes = store => { > - + + diff --git a/console/webpack/dev.config.js b/console/webpack/dev.config.js index a7747b16942..985ea99e213 100755 --- a/console/webpack/dev.config.js +++ b/console/webpack/dev.config.js @@ -20,6 +20,12 @@ const webpackIsomorphicToolsPlugin = new WebpackIsomorphicToolsPlugin( // const { UnusedFilesWebpackPlugin } = require('unused-files-webpack-plugin'); +const getRandomHexString = () => { + return Math.random() + .toString(16) + .slice(2); +}; + module.exports = { mode: 'development', devtool: 'inline-source-map', @@ -147,6 +153,10 @@ module.exports = { __DEVELOPMENT__: true, __DEVTOOLS__: true, // <-------- DISABLE redux-devtools HERE }), + // set global consts + new webpack.DefinePlugin({ + CONSOLE_ASSET_VERSION: JSON.stringify(getRandomHexString()), + }), webpackIsomorphicToolsPlugin.development(), ], }; diff --git a/console/webpack/prod.config.js b/console/webpack/prod.config.js index fc5d9b31b42..929c5a1f49d 100755 --- a/console/webpack/prod.config.js +++ b/console/webpack/prod.config.js @@ -22,6 +22,12 @@ const cleanOptions = { dry: false, }; +const getRandomHexString = () => { + return Math.random() + .toString(16) + .slice(2); +}; + module.exports = { mode: 'production', context: path.resolve(__dirname, '..'), @@ -187,6 +193,7 @@ module.exports = { // Useful to reduce the size of client-side libraries, e.g. react NODE_ENV: JSON.stringify('production'), }, + CONSOLE_ASSET_VERSION: JSON.stringify(getRandomHexString()), }), ], };