App download indicator.

This commit is contained in:
Thomas E Lackey 2020-06-08 16:10:00 -05:00
parent d3772602c6
commit dccd61c0c9
7 changed files with 108 additions and 47 deletions

View File

@ -14,7 +14,7 @@ First start the server:
Then start the Webpack devserver.
```bash
cd packages/consoe-app
cd packages/console-app
yarn start
```

View File

@ -22,20 +22,19 @@ system:
services:
app:
prefix: '/app'
server: 'http://127.0.0.1:5999'
server: 'https://xbox.local'
wns:
server: 'http://127.0.0.1:9473/api'
webui: 'http://127.0.0.1:9473/webui'
server: 'https://xbox.local/dxos/wns/api'
webui: 'https://xbox.local/dxos/wns/webui'
signal:
server: 'http://127.0.0.1:4000'
api: 'http://127.0.0.1:4000'
server: 'wss://xbox.local/dxos/signal'
api: 'https://xbox.local/dxos/signal/'
ipfs:
server: '/ip4/127.0.0.1/tcp/5001'
gateway: '/ip4//127.0.0.1:8888/ipfs/'
webui: 'http://127.0.0.1:5001/webui'
server: 'https://xbox.local/dxos/ipfs/api'
gateway: 'https://xbox.local/dxos/ipfs/gateway'
wellknown:
endpoint: 'http://127.0.0.1:9000/.well-known/dxos'
endpoint: 'https://xbox.local/.well-known/dxos'

View File

@ -0,0 +1,30 @@
//
// Copyright 2020 DxOS
//
import React from 'react';
import YesIcon from '@material-ui/icons/CheckCircleOutline';
import NoIcon from '@material-ui/icons/RadioButtonUnchecked';
import { makeStyles } from '@material-ui/core/styles';
const useStyles = makeStyles(theme => ({
error: {
color: theme.palette.error.main
},
on: {
color: theme.palette.primary[500]
},
off: {
color: 'transparent'
}
}));
export const BooleanIcon = ({ yes = false, error = false }) => {
const classes = useStyles();
return (yes
? <YesIcon className={classes.on} />
: <NoIcon className={error ? classes.error : classes.off} />
);
};

View File

@ -3,36 +3,42 @@
//
import React, { useContext } from 'react';
import { useQuery } from '@apollo/react-hooks';
import WNS_RECORDS from '../../../gql/wns_records.graphql';
import { ConsoleContext, useQueryStatusReducer, useSorter } from '../../../hooks';
import Link from '@material-ui/core/Link';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import TableBody from '@material-ui/core/TableBody';
import moment from 'moment';
import { getServiceUrl } from '../../../util/config';
import { BooleanIcon } from '../../../components/BooleanIcon';
import Table from '../../../components/Table';
import TableCell from '../../../components/TableCell';
import moment from 'moment';
import { ConsoleContext, useQueryStatusReducer, useSorter } from '../../../hooks';
import { getServiceUrl } from '../../../util/config';
import IPFS_STATUS from '../../../gql/ipfs_status.graphql';
import WNS_RECORDS from '../../../gql/wns_records.graphql';
const AppRecords = () => {
const { config } = useContext(ConsoleContext);
const [sorter, sortBy] = useSorter('createTime', false);
const data = useQueryStatusReducer(useQuery(WNS_RECORDS, {
const appResponse = useQueryStatusReducer(useQuery(WNS_RECORDS, {
pollInterval: config.api.intervalQuery,
variables: { type: 'wrn:app' }
}));
if (!data) {
// TODO(telackey): Does this also need an interval?
const ipfsResponse = useQueryStatusReducer(useQuery(IPFS_STATUS));
if (!appResponse || !ipfsResponse) {
return null;
}
const records = data.wns_records.json;
const appData = appResponse.wns_records.json;
const ipfsData = JSON.parse(ipfsResponse.ipfs_status.json);
const localRefs = new Set(ipfsData.refs.local);
// TODO(burdon): Test if app is deployed.
const getAppUrl = ({ name, version }) => {
@ -47,8 +53,12 @@ const AppRecords = () => {
pathComponents.push(config.services.app.prefix.substring(1));
}
pathComponents.push(`${name}@${version}`);
return pathComponents.join('/');
if (version) {
pathComponents.push(`${name}@${version}`);
} else {
pathComponents.push(name);
}
return `${pathComponents.join('/')}/`;
};
return (
@ -56,26 +66,29 @@ const AppRecords = () => {
<TableHead>
<TableRow>
<TableCell onClick={sortBy('name')}>Identifier</TableCell>
<TableCell onClick={sortBy('attributes.displayName')}>Name</TableCell>
<TableCell onClick={sortBy('version')} size='small'>Version</TableCell>
<TableCell onClick={sortBy('createTime')} size='small'>Created</TableCell>
<TableCell onClick={sortBy('attributes.displayName')}>Name</TableCell>
<TableCell>Link</TableCell>
<TableCell size='small'>Downloaded</TableCell>
</TableRow>
</TableHead>
<TableBody>
{records.sort(sorter).map(({ id, name, version, createTime, attributes: { displayName, publicUrl } }) => {
const link = getAppUrl({ id, name, version, publicUrl });
{appData.sort(sorter).map(({ id, name, version, createTime, attributes: { displayName, publicUrl, package: hash } }) => {
const verLink = getAppUrl({ id, name, version, publicUrl });
const appLink = getAppUrl({ id, name, publicUrl });
return (
<TableRow key={id} size='small'>
<TableCell monospace>{name}</TableCell>
<TableCell monospace>{version}</TableCell>
<TableCell>{moment.utc(createTime).fromNow()}</TableCell>
<TableCell monospace>
<Link href={appLink} target={name}>{name}</Link>
</TableCell>
<TableCell>{displayName}</TableCell>
<TableCell monospace>
{link && (
<Link href={link} target={name}>{link}</Link>
)}
<Link href={verLink} target={version}>{version}</Link>
</TableCell>
<TableCell>{moment.utc(createTime).fromNow()}</TableCell>
<TableCell>
<BooleanIcon yes={localRefs && localRefs.has(hash)} />
</TableCell>
</TableRow>
);

View File

@ -1,7 +1,7 @@
{
"build": {
"name": "@dxos/console-app",
"buildDate": "2020-06-01T01:13:48.575Z",
"buildDate": "2020-06-08T18:45:46.717Z",
"version": "1.0.0-beta.0"
}
}

View File

@ -3,8 +3,6 @@
# NOTE: Set CONFIG_FILE to swap out this config file.
#
# TODO(burdon): Set defaults.
app:
title: 'Console'
org': 'DxOS'
@ -24,20 +22,19 @@ system:
services:
app:
prefix: '/app'
server: 'http://127.0.0.1:5999'
server: 'https://xbox.local'
wns:
server: 'https://node1.dxos.network/wns/api'
webui: 'https://node1.dxos.network/wns/webui'
server: 'https://xbox.local/dxos/wns/api'
webui: 'https://xbox.local/dxos/wns/webui'
signal:
server: 'http://127.0.0.1:4000'
api: 'http://127.0.0.1:4000'
server: 'wss://xbox.local/dxos/signal'
api: 'https://xbox.local/dxos/signal/status'
ipfs:
server: '/ip4/127.0.0.1/tcp/5001'
gateway: '/ip4//127.0.0.1:8888/ipfs/'
webui: 'http://127.0.0.1:5001/webui'
server: 'https://xbox.local/dxos/ipfs/api'
gateway: 'https://xbox.local/dxos/ipfs/gateway'
wellknown:
endpoint: 'http://127.0.0.1:9000/.well-known/dxos'
endpoint: 'https://xbox.local/.well-known/dxos'

View File

@ -21,14 +21,36 @@ export const ipfsResolvers = {
// NOTE: Hangs if server not running.
const ipfs = new IpfsHttpClient(config.services.ipfs.server);
const id = await ipfs.id();
const version = await ipfs.version();
const status = await ipfs.id();
const peers = await ipfs.swarm.peers();
const stats = await ipfs.stats.repo();
// Do not expose the repo path.
delete stats['repoPath'];
const refs = [];
for await (const ref of ipfs.refs.local()) {
if (ref.err) {
log(ref.err);
} else {
refs.push(ref.ref);
}
}
return {
timestamp: new Date().toUTCString(),
json: JSON.stringify({
id,
version,
status
repo: {
stats
},
refs: {
local: refs
},
swarm: {
peers
}
})
};
}