forked from cerc-io/laconic-console
App download indicator.
This commit is contained in:
parent
d3772602c6
commit
dccd61c0c9
@ -14,7 +14,7 @@ First start the server:
|
||||
Then start the Webpack devserver.
|
||||
|
||||
```bash
|
||||
cd packages/consoe-app
|
||||
cd packages/console-app
|
||||
yarn start
|
||||
```
|
||||
|
||||
|
@ -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'
|
||||
|
30
packages/console-app/src/components/BooleanIcon.js
Normal file
30
packages/console-app/src/components/BooleanIcon.js
Normal 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} />
|
||||
);
|
||||
};
|
@ -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>
|
||||
);
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
}
|
||||
})
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user