This commit is contained in:
richburdon 2020-05-23 20:38:52 -04:00
parent 9eb1d0de16
commit b24fdfc57c
8 changed files with 55 additions and 31 deletions

View File

@ -1,11 +1,14 @@
{ {
"publicUrl": "/app",
"port": 4000,
"path": "/api",
"app": { "app": {
"org": "DxOS", "org": "DxOS",
"theme": "dark", "theme": "dark",
"title": "Console", "title": "Console",
"website": "https://dxos.org" "website": "https://dxos.org",
"publicUrl": "/console"
},
"graphql": {
"path": "/api",
"port": 4000,
"pollInterval": 10000
} }
} }

View File

@ -12,7 +12,7 @@
"analyzer": "webpack --config webpack-analyzer.config.js", "analyzer": "webpack --config webpack-analyzer.config.js",
"build": "npm run clean && npm run build:module && npm run build:production", "build": "npm run clean && npm run build:module && npm run build:production",
"build:module": "babel ./src --out-dir ./dist/es --ignore \"**/*.test.js\" --source-maps inline", "build:module": "babel ./src --out-dir ./dist/es --ignore \"**/*.test.js\" --source-maps inline",
"build:production": "PUBLIC_URL=/app webpack --mode production", "build:production": "PUBLIC_URL=/console webpack --mode production",
"clean": "rm -rf dist", "clean": "rm -rf dist",
"lint": "semistandard 'src/**/*.js'", "lint": "semistandard 'src/**/*.js'",
"start": "VERBOSE=true webpack-dev-server --mode development", "start": "VERBOSE=true webpack-dev-server --mode development",

View File

@ -8,16 +8,20 @@ import { InMemoryCache } from 'apollo-cache-inmemory';
const defaultServer = `${window.location.protocol}//${window.location.hostname}`; const defaultServer = `${window.location.protocol}//${window.location.hostname}`;
export const graphqlApi = config => {
const { graphql: { server = defaultServer, port = 80, path = '/graphql' } } = config;
return `${server}:${port}${path}`;
};
// https://www.apollographql.com/docs/react/api/apollo-client/ // https://www.apollographql.com/docs/react/api/apollo-client/
export const clientFactory = config => { export const clientFactory = config => {
const { server = defaultServer, port = 80, path = '/graphql' } = config;
// TODO(burdon): Authentication: send signed message to server (from client wallet). // TODO(burdon): Authentication: send signed message to server (from client wallet).
// https://www.apollographql.com/docs/react/networking/authentication/ // https://www.apollographql.com/docs/react/networking/authentication/
// https://www.apollographql.com/docs/link/ // https://www.apollographql.com/docs/link/
const link = createHttpLink({ const link = createHttpLink({
uri: `${server}:${port}${path}` uri: graphqlApi(config)
}); });
return new ApolloClient({ return new ApolloClient({

View File

@ -5,13 +5,14 @@
import React from 'react'; import React from 'react';
import { makeStyles } from '@material-ui/core'; import { makeStyles } from '@material-ui/core';
import MuiAppBar from '@material-ui/core/AppBar'; import MuiAppBar from '@material-ui/core/AppBar';
import MuiLink from '@material-ui/core/Link'; import Link from '@material-ui/core/Link';
import Toolbar from '@material-ui/core/Toolbar'; import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography'; import Typography from '@material-ui/core/Typography';
import blueGrey from '@material-ui/core/colors/blueGrey'; import blueGrey from '@material-ui/core/colors/blueGrey';
import PublicIcon from '@material-ui/icons/Public'; import GraphQLIcon from '@material-ui/icons/Adb';
import DxOSIcon from '../icons/DXOS'; import DxOSIcon from '../icons/DXOS';
import { graphqlApi } from '../client';
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles((theme) => ({
offset: theme.mixins.denseToolbar, offset: theme.mixins.denseToolbar,
@ -45,18 +46,24 @@ const AppBar = ({ config }) => {
<> <>
<MuiAppBar position="fixed"> <MuiAppBar position="fixed">
<Toolbar variant="dense"> <Toolbar variant="dense">
<MuiLink href="/"> <Link href="/">
<div className={classes.logo}> <div className={classes.logo}>
<DxOSIcon /> <DxOSIcon />
</div> </div>
</MuiLink> </Link>
<div className={classes.title}> <div className={classes.title}>
<Typography variant="h6">{config.app.title}</Typography> <Typography variant="h6">{config.app.title}</Typography>
</div> </div>
<div> <div>
<MuiLink href={config.app.website} className={classes.link} rel="noreferrer" target="_blank"> <Link
<PublicIcon /> className={classes.link}
</MuiLink> href={graphqlApi(config)}
rel="noreferrer"
target="_blank"
title="Console GraphQL"
>
<GraphQLIcon />
</Link>
</div> </div>
</Toolbar> </Toolbar>
</MuiAppBar> </MuiAppBar>

View File

@ -5,12 +5,12 @@
import isObject from 'lodash.isobject'; import isObject from 'lodash.isobject';
import omit from 'lodash.omit'; import omit from 'lodash.omit';
import transform from 'lodash.transform'; import transform from 'lodash.transform';
import React from 'react'; import React, { useContext } from 'react';
import { useQuery } from '@apollo/react-hooks'; import { useQuery } from '@apollo/react-hooks';
import Json from '../components/Json'; import Json from '../components/Json';
import { useQueryStatusReducer } from '../hooks'; import { ConsoleContext, useQueryStatusReducer } from '../hooks';
import QUERY_STATUS from '../../gql/status.graphql'; import QUERY_STATUS from '../../gql/status.graphql';
@ -19,7 +19,9 @@ const removeTypename = data => transform(data, (result, value, key) => {
}); });
const Status = () => { const Status = () => {
const data = useQueryStatusReducer(useQuery(QUERY_STATUS, { pollInterval: 5000 })); const { config } = useContext(ConsoleContext);
const data = useQueryStatusReducer(useQuery(QUERY_STATUS, { pollInterval: config.graphql.pollInterval }));
if (!data) { if (!data) {
return null; return null;
} }

View File

@ -5,9 +5,12 @@
import clsx from 'clsx'; import clsx from 'clsx';
import React, { useContext, useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
import { makeStyles } from '@material-ui/core'; import { makeStyles } from '@material-ui/core';
import Link from '@material-ui/core/Link';
import Toolbar from '@material-ui/core/Toolbar';
import ErrorIcon from '@material-ui/icons/Error'; import ErrorIcon from '@material-ui/icons/Error';
import LoadingIcon from '@material-ui/icons/Wifi'; import LoadingIcon from '@material-ui/icons/Wifi';
import RunningIcon from '@material-ui/icons/CheckCircle'; import RunningIcon from '@material-ui/icons/CheckCircle';
import PublicIcon from '@material-ui/icons/Public';
import grey from '@material-ui/core/colors/grey'; import grey from '@material-ui/core/colors/grey';
import green from '@material-ui/core/colors/green'; import green from '@material-ui/core/colors/green';
import red from '@material-ui/core/colors/red'; import red from '@material-ui/core/colors/red';
@ -22,9 +25,7 @@ const useStyles = makeStyles((theme) => ({
flex: 1, flex: 1,
justifyContent: 'space-around', justifyContent: 'space-around',
backgroundColor: grey[900], backgroundColor: grey[900],
color: '#EEE', color: grey[400]
height: 32,
padding: 4
}, },
left: { left: {
width: 160 width: 160
@ -40,6 +41,9 @@ const useStyles = makeStyles((theme) => ({
icon: { icon: {
margin: '0 2px' margin: '0 2px'
}, },
link: {
color: grey[400]
},
error: { error: {
color: red[500] color: red[500]
}, },
@ -82,14 +86,18 @@ const StatusBar = () => {
}; };
return ( return (
<div className={classes.root}> <Toolbar variant="dense" className={classes.root}>
<div className={classes.left} /> <div className={classes.left}>
<Link className={classes.link} href={config.app.website} rel="noreferrer" target="_blank">
<PublicIcon />
</Link>
</div>
<div className={classes.center}>(c) {config.app.org} {version}</div> <div className={classes.center}>(c) {config.app.org} {version}</div>
<div className={classes.right}> <div className={classes.right}>
<LoadingIcon className={clsx(classes.icon, isLoading && classes.loading)} /> <LoadingIcon className={clsx(classes.icon, isLoading && classes.loading)} />
<StatusIcon error={error} /> <StatusIcon error={error} />
</div> </div>
</div> </Toolbar>
); );
}; };

View File

@ -1,7 +1,7 @@
{ {
"build": { "build": {
"name": "@dxos/console-client", "name": "@dxos/console-client",
"buildDate": "2020-05-23T23:08:59.032Z", "buildDate": "2020-05-24T00:17:36.206Z",
"version": "1.0.0-beta.0" "version": "1.0.0-beta.0"
} }
} }

View File

@ -42,12 +42,11 @@ const app = express();
// React app // React app
// //
const { publicUrl } = config; const { app: { publicUrl } } = config;
app.get(`${publicUrl}(/:filePath)?`, (req, res) => { app.get(`${publicUrl}(/:filePath)?`, (req, res) => {
const { filePath = 'index.html' } = req.params; const { filePath = 'index.html' } = req.params;
const file = path.join(__dirname, '../../../node_modules/@dxos/console-client/dist/production', filePath); const file = path.join(__dirname, '../../../node_modules/@dxos/console-client/dist/production', filePath);
console.log(__dirname, file);
res.sendFile(file); res.sendFile(file);
}); });
@ -69,7 +68,8 @@ const server = new ApolloServer({
}, },
tabs: [ tabs: [
{ {
endpoint: config.path, name: 'Status',
endpoint: config.graphql.path,
query: print(gql(QUERY_STATUS)) query: print(gql(QUERY_STATUS))
} }
] ]
@ -83,13 +83,13 @@ const server = new ApolloServer({
server.applyMiddleware({ server.applyMiddleware({
app, app,
path: config.path path: config.graphql.path
}); });
// //
// Start server // Start server
// //
app.listen({ port: config.port }, () => { app.listen({ port: config.graphql.port }, () => {
log(`Running: http://localhost:${config.port}`); log(`Running: http://localhost:${config.graphql.port}`);
}); });