Compare commits

...

21 Commits
v0.2.0 ... main

Author SHA1 Message Date
1e1149eb78 Handle undefined attributes in records resolver (#61)
Some checks failed
Publish ApplicationRecord to Registry / cns_publish (release) Failing after 1m31s
Publish npm package to gitea / npm_publish (18.x) (release) Successful in 3m20s
Part of [Create a public laconicd testnet](https://www.notion.so/Create-a-public-laconicd-testnet-896a11bdd8094eff8f1b49c0be0ca3b8)

Handles the error in `LOOKUP` tab in the console:
```bash
Error: Cannot destructure property 'limit' of 'attributes' as it is undefined.
```

Co-authored-by: IshaVenikar <ishavenikar7@gmail.com>
Reviewed-on: #61
Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Co-committed-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
2024-10-23 08:00:12 +00:00
139fb37bef Implement pagination for registry records table (#60)
Part of [Create a public laconicd testnet](https://www.notion.so/Create-a-public-laconicd-testnet-896a11bdd8094eff8f1b49c0be0ca3b8)
Handles cerc-io/laconic-console#59
Requires cerc-io/registry-sdk#27

![image](/attachments/095cf131-19ef-4acc-9ffe-bcbe2f9dad77)
![image](/attachments/684722d3-b9df-44ae-8622-5bacd2dc2a3f)

Co-authored-by: IshaVenikar <ishavenikar7@gmail.com>
Reviewed-on: #60
Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Co-committed-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
2024-09-06 05:23:17 +00:00
4c22335313 Bump (#58)
All checks were successful
Publish npm package to gitea / npm_publish (18.x) (release) Successful in 3m0s
Publish ApplicationRecord to Registry / cns_publish (release) Successful in 1m27s
Reviewed-on: #58
Co-authored-by: Thomas E Lackey <telackey@bozemanpass.com>
Co-committed-by: Thomas E Lackey <telackey@bozemanpass.com>
2024-08-21 19:29:40 +00:00
5a09cdd79a Add CI webapp deployment (#57)
All checks were successful
Publish npm package to gitea / npm_publish (18.x) (release) Successful in 2m55s
Publish ApplicationRecord to Registry / cns_publish (release) Successful in 1m29s
Reviewed-on: #57
Co-authored-by: Thomas E Lackey <telackey@bozemanpass.com>
Co-committed-by: Thomas E Lackey <telackey@bozemanpass.com>
2024-08-14 23:48:59 +00:00
fc83856e11 Merge pull request 'Update package version' (#56) from zramsay-patch-2 into main
All checks were successful
Publish npm package to gitea / npm_publish (18.x) (release) Successful in 2m52s
Reviewed-on: #56
2024-08-09 19:10:42 +00:00
c1e368b3b0 Update package version 2024-08-09 19:09:54 +00:00
db449e9fe2 Merge pull request 'style/laconic-colors' (#55) from style/laconic-colors into main
Some checks failed
Publish npm package to gitea / npm_publish (18.x) (release) Has been cancelled
Reviewed-on: #55
2024-08-09 17:49:56 +00:00
Monkey
b1f95b488c add favicon, hard code site title 2024-08-09 10:16:13 -04:00
Monkey
fc76478b8a background for sidebar, tabs and footer darker, inner container lighter 2024-08-09 00:02:37 -04:00
4afadb9502 style: json tree view 2024-08-08 23:44:55 -04:00
Monkey
bff6749a91 lighten background color, footer background color and border 2024-08-08 23:44:49 -04:00
a4c15a4d3f chore: undo json comment 2024-08-08 23:16:25 -04:00
3ead0ee0d0 style: appbar logo 2024-08-08 23:00:38 -04:00
aa794637d1 style: font 2024-08-08 22:45:58 -04:00
Monkey
956c84c17e sidebar icon selected color matches font color 2024-08-08 22:36:39 -04:00
ccb31956a8 style: some more colors 2024-08-08 22:24:20 -04:00
01122eb7a8 style: set primary to laconic blue 2024-08-08 22:12:38 -04:00
740143ce7d Update package version (#54)
All checks were successful
Publish npm package to gitea / npm_publish (18.x) (release) Successful in 2m50s
Part of [Rename laconic2d to laconicd](https://www.notion.so/Rename-laconic2d-to-laconicd-9028d0c020d24d1288e92ebcb773d7a7)

Reviewed-on: #54
Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Co-committed-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
2024-07-25 07:04:11 +00:00
4150076469 Rename laconic2d to laconicd repo in readme (#53)
Part of [Rename laconic2d to laconicd](https://www.notion.so/Rename-laconic2d-to-laconicd-9028d0c020d24d1288e92ebcb773d7a7)

Reviewed-on: #53
Co-authored-by: Nabarun <nabarun@deepstacksoft.com>
Co-committed-by: Nabarun <nabarun@deepstacksoft.com>
2024-07-23 04:54:40 +00:00
7330d03c3c Upgrade registry-sdk package version (#51)
Part of [laconicd testnet validator enrollment](https://www.notion.so/laconicd-testnet-validator-enrollment-6fc1d3cafcc64fef8c5ed3affa27c675)

Reviewed-on: #51
Co-authored-by: Nabarun <nabarun@deepstacksoft.com>
Co-committed-by: Nabarun <nabarun@deepstacksoft.com>
2024-07-22 06:22:21 +00:00
06726b019d Upgrade registry-sdk version with changes for renaming laconic2d to laconicd (#50)
Part of https://www.notion.so/Rename-laconic2d-to-laconicd-9028d0c020d24d1288e92ebcb773d7a7

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
Reviewed-on: #50
Co-authored-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
Co-committed-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
2024-04-02 13:57:45 +00:00
23 changed files with 604 additions and 311 deletions

View File

@ -0,0 +1,36 @@
name: Publish ApplicationRecord to Registry
on:
release:
types: [published]
env:
CERC_REGISTRY_USER_KEY: ${{ secrets.CICD_VAASL_LACONIC_USER_KEY }}
CERC_REGISTRY_BOND_ID: ${{ secrets.CICD_VAASL_LACONIC_BOND_ID }}
CERC_REGISTRY_DEPLOYMENT_HOSTNAME: ${{ vars.CERC_REGISTRY_DEPLOYMENT_HOSTNAME }}
LACONIC_HOSTED_CONFIG_services_wns_server: ${{ vars.LACONIC_HOSTED_CONFIG_SERVICES_WNS_SERVER }}
LACONIC_HOSTED_CONFIG_services_wns_webui: ${{ vars.LACONIC_HOSTED_CONFIG_SERVICES_WNS_WEBUI }}
LACONIC_HOSTED_CONFIG_services_signal_api: ${{ vars.LACONIC_HOSTED_CONFIg_SERVICES_SIGNAL_API }}
LACONIC_HOSTED_CONFIG_app_api_url: ${{ vars.LACONIC_HOSTED_CONFIg_APP_API_URL }}
jobs:
cns_publish:
runs-on: ubuntu-latest
steps:
- name: "Clone project repository"
uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18
- name: "Enable Yarn"
run: corepack enable
- name: "Install registry CLI"
run: |
npm config set @cerc-io:registry https://git.vdb.to/api/packages/cerc-io/npm/
npm install -g @cerc-io/laconic-registry-cli
- name: "Install jq"
run: apt -y update && apt -y install jq
- name: "Publish Application Record"
run: scripts/publish-app-record.sh
- name: "Request Deployment"
run: scripts/request-app-deployment.sh

View File

@ -7,14 +7,14 @@ User interface for submitting and reading records registered on Laconic.
## Development
* Clone the required repos:
* [laconic2d](https://git.vdb.to/cerc-io/laconic2d)
* [laconicd](https://git.vdb.to/cerc-io/laconicd)
```bash
git clone git@git.vdb.to:cerc-io/laconic2d.git
git clone git@git.vdb.to:cerc-io/laconicd.git
```
* Run the `laconic2d` chain:
* In [laconic2d](https://git.vdb.to/cerc-io/laconic2d) repo, start the chain
* Run the `laconicd` chain:
* In [laconicd](https://git.vdb.to/cerc-io/laconicd) repo, start the chain
```bash
./scripts/init.sh clean
@ -63,7 +63,7 @@ User interface for submitting and reading records registered on Laconic.
* Export the private key using:
```bash
laconic2d keys export alice --keyring-backend test --unarmored-hex --unsafe
laconicd keys export alice --keyring-backend test --unarmored-hex --unsafe
```
* Copy the private key exported above and assign it to variable `PRIVATE_KEY` in the `.env` file.

7
build-webapp.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
yarn
LACONIC_HOSTED_CONFIG_FILE=config-hosted.yml yarn build
rm -rf dist/es
mv dist/production "$1"

View File

@ -5,7 +5,7 @@
app:
title: 'Console'
org': 'Laconic'
org: 'Laconic'
theme: 'dark'
website: 'https://laconic.com'
publicUrl: '/console'

View File

@ -1,6 +1,6 @@
{
"name": "@cerc-io/console-app",
"version": "0.2.0",
"version": "0.2.5",
"description": "Laconic Console",
"repository": "https://github.com/cerc-io/laconic-console",
"main": "dist/es/index.js",
@ -31,7 +31,7 @@
"@apollo/react-components": "^4.0.0",
"@apollo/react-hooks": "^4.0.0",
"@babel/runtime": "^7.21.0",
"@cerc-io/registry-sdk": "^0.2.0",
"@cerc-io/registry-sdk": "^0.2.8",
"@lirewine/debug": "1.0.0-beta.78",
"@lirewine/gem-core": "1.0.0-beta.28",
"@lirewine/react-ux": "1.1.0-beta.1",

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,10 +1,18 @@
<!DOCTYPE html>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title><%= title %></title>
</head>
<body>
<div id="root"></div>
</body>
<head>
<meta charset="utf-8" />
<title>Laconic | Console</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap"
rel="stylesheet" />
</head>
<body>
<div id="root"></div>
</body>
</html>

View File

@ -1,32 +0,0 @@
#!/bin/bash
set -euo pipefail
for appdir in `find ./packages -name '*-app' -type d | grep -v node_modules`; do
pushd $appdir
WNS_ORG="${WNS_ORG:-dxos}"
PKG_CHANNEL="${PKG_CHANNEL:-}"
PKG_NAME=`cat package.json | jq -r '.name' | cut -d'/' -f2- | sed 's/-app$//'`
WNS_NAME="$WNS_ORG/$PKG_NAME"
cat <<EOF > app.yml
name: $PKG_NAME
build: yarn dist
EOF
cat app.yml
echo "wrn://${WNS_ORG}/application/${PKG_NAME}${PKG_CHANNEL}"
yarn clean
yarn -s wire app build
if [ -d "dist/production" ]; then
yarn -s wire app publish --path './dist/production'
else
yarn -s wire app publish
fi
yarn -s wire app register --name "wrn://${WNS_ORG}/application/${PKG_NAME}${PKG_CHANNEL}"
popd
done

69
scripts/publish-app-record.sh Executable file
View File

@ -0,0 +1,69 @@
#!/bin/bash
set -e
RECORD_FILE=tmp.rf.$$
CONFIG_FILE=`mktemp`
CERC_APP_TYPE=${CERC_APP_TYPE:-"webapp"}
CERC_REPO_REF=${CERC_REPO_REF:-${GITHUB_SHA:-`git log -1 --format="%H"`}}
CERC_IS_LATEST_RELEASE=${CERC_IS_LATEST_RELEASE:-"true"}
rcd_name=$(jq -r '.name' package.json | sed 's/null//')
rcd_desc=$(jq -r '.description' package.json | sed 's/null//')
rcd_repository=$(jq -r '.repository' package.json | sed 's/null//')
rcd_homepage=$(jq -r '.homepage' package.json | sed 's/null//')
rcd_license=$(jq -r '.license' package.json | sed 's/null//')
rcd_author=$(jq -r '.author' package.json | sed 's/null//')
rcd_app_version=$(jq -r '.version' package.json | sed 's/null//')
cat <<EOF > "$CONFIG_FILE"
services:
registry:
rpcEndpoint: '${CERC_REGISTRY_RPC_ENDPOINT:-http://testnet-a-1.dev.vaasl.io:26657}'
gqlEndpoint: '${CERC_REGISTRY_GQL_ENDPOINT:-http://testnet-a-1.dev.vaasl.io:9473/api}'
chainId: ${CERC_REGISTRY_CHAIN_ID:-laconic-08062024}
gas: 900000
fees: 900000alnt
EOF
next_ver=$(laconic -c $CONFIG_FILE registry record list --type ApplicationRecord --all --name "$rcd_name" 2>/dev/null | jq -r -s ".[] | sort_by(.createTime) | reverse | [ .[] | select(.bondId == \"$CERC_REGISTRY_BOND_ID\") ] | .[0].attributes.version" | awk -F. -v OFS=. '{$NF += 1 ; print}')
if [ -z "$next_ver" ] || [ "1" == "$next_ver" ]; then
next_ver=0.0.1
fi
cat <<EOF | sed '/.*: ""$/d' > "$RECORD_FILE"
record:
type: ApplicationRecord
version: ${next_ver}
name: "$rcd_name"
description: "$rcd_desc"
homepage: "$rcd_homepage"
license: "$rcd_license"
author: "$rcd_author"
repository:
- "$rcd_repository"
repository_ref: "$CERC_REPO_REF"
app_version: "$rcd_app_version"
app_type: "$CERC_APP_TYPE"
EOF
cat $RECORD_FILE
RECORD_ID=$(laconic -c $CONFIG_FILE registry record publish --filename $RECORD_FILE --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} | jq -r '.id')
echo $RECORD_ID
if [ -z "$CERC_REGISTRY_APP_LRN" ]; then
authority=$(echo "$rcd_name" | cut -d'/' -f1 | sed 's/@//')
app=$(echo "$rcd_name" | cut -d'/' -f2-)
CERC_REGISTRY_APP_LRN="lrn://$authority/applications/$app"
fi
laconic -c $CONFIG_FILE registry name set --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} "$CERC_REGISTRY_APP_LRN@${rcd_app_version}" "$RECORD_ID"
laconic -c $CONFIG_FILE registry name set --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} "$CERC_REGISTRY_APP_LRN@${CERC_REPO_REF}" "$RECORD_ID"
if [ "true" == "$CERC_IS_LATEST_RELEASE" ]; then
laconic -c $CONFIG_FILE registry name set --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} "$CERC_REGISTRY_APP_LRN" "$RECORD_ID"
fi
rm -f $RECORD_FILE $CONFIG_FILE

View File

@ -0,0 +1,61 @@
#!/bin/bash
set -e
RECORD_FILE=tmp.rf.$$
CONFIG_FILE=`mktemp`
rcd_name=$(jq -r '.name' package.json | sed 's/null//' | sed 's/^@//')
rcd_app_version=$(jq -r '.version' package.json | sed 's/null//')
cat <<EOF > "$CONFIG_FILE"
services:
registry:
rpcEndpoint: '${CERC_REGISTRY_RPC_ENDPOINT:-http://testnet-a-2.dev.vaasl.io:26657}'
gqlEndpoint: '${CERC_REGISTRY_GQL_ENDPOINT:-http://testnet-a-2.dev.vaasl.io:9473/api}'
chainId: ${CERC_REGISTRY_CHAIN_ID:-laconic-08062024}
gas: 900000
fees: 900000alnt
EOF
if [ -z "$CERC_REGISTRY_APP_LRN" ]; then
authority=$(echo "$rcd_name" | cut -d'/' -f1 | sed 's/@//')
app=$(echo "$rcd_name" | cut -d'/' -f2-)
CERC_REGISTRY_APP_LRN="lrn://$authority/applications/$app"
fi
APP_RECORD=$(laconic -c $CONFIG_FILE registry name resolve "$CERC_REGISTRY_APP_LRN" | jq '.[0]')
if [ -z "$APP_RECORD" ] || [ "null" == "$APP_RECORD" ]; then
echo "No record found for $CERC_REGISTRY_APP_LRN."
exit 1
fi
MY_ACCOUNT=$(laconic -c $CONFIG_FILE registry account get --user-key "${CERC_REGISTRY_USER_KEY}" | jq -r '.[0].address')
cat <<EOF | sed '/.*: ""$/d' > "$RECORD_FILE"
record:
type: ApplicationDeploymentRequest
version: 1.0.0
name: "$rcd_name@$rcd_app_version"
application: "$CERC_REGISTRY_APP_LRN@$rcd_app_version"
dns: "$CERC_REGISTRY_DEPLOYMENT_HOSTNAME"
deployment: "$CERC_REGISTRY_DEPLOYMENT_LRN"
to: $MY_ACCOUNT
config:
env:
CERC_WEBAPP_DEBUG: "$rcd_app_version"
LACONIC_HOSTED_CONFIG_services_wns_server: "$LACONIC_HOSTED_CONFIG_services_wns_server"
LACONIC_HOSTED_CONFIG_services_wns_webui: "$LACONIC_HOSTED_CONFIG_services_wns_webui"
LACONIC_HOSTED_CONFIG_services_signal_api: "$LACONIC_HOSTED_CONFIG_services_signal_api"
LACONIC_HOSTED_CONFIG_app_api_url: "$LACONIC_HOSTED_CONFIG_app_api_url"
meta:
note: "Added by CI @ `date`"
repository: "`git remote get-url origin`"
repository_ref: "${GITHUB_SHA:-`git log -1 --format="%H"`}"
EOF
cat $RECORD_FILE
RECORD_ID=$(laconic -c $CONFIG_FILE registry record publish --filename $RECORD_FILE --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} | jq -r '.id')
echo $RECORD_ID
rm -f $RECORD_FILE $CONFIG_FILE

View File

@ -2,16 +2,17 @@
// Copyright 2020 DXOS.org
//
import React from 'react';
import { makeStyles } from '@material-ui/core';
import MuiAppBar from '@material-ui/core/AppBar';
import Link from '@material-ui/core/Link';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import blueGrey from '@material-ui/core/colors/blueGrey';
import React from "react";
import { makeStyles } from "@material-ui/core";
import MuiAppBar from "@material-ui/core/AppBar";
import Divider from "@material-ui/core/Divider";
import Link from "@material-ui/core/Link";
import Toolbar from "@material-ui/core/Toolbar";
import Typography from "@material-ui/core/Typography";
import blueGrey from "@material-ui/core/colors/blueGrey";
// import GraphQLIcon from '@material-ui/icons/Adb';
// import LaconicIcon from '../icons/Laconic';
import LaconicIcon from "../icons/Logo";
// import { graphqlApi } from '../client';
const useStyles = makeStyles((theme) => ({
@ -21,26 +22,34 @@ const useStyles = makeStyles((theme) => ({
marginRight: theme.spacing(2),
color: theme.palette.grey[800],
'& svg': {
"& svg": {
width: 100,
height: 48
}
height: 48,
},
},
logoLink: {
lineHeight: 0
lineHeight: 0,
},
title: {
display: 'flex',
display: "flex",
flex: 1,
marginTop: 2,
color: theme.palette.grey[800]
color: "#FBFBFB",
},
link: {
color: blueGrey[900]
}
color: blueGrey[900],
},
divider: {
backgroundColor: theme.palette.text.primary,
width: "1px",
height: "20px",
alignSelf: "center",
marginRight: 14,
},
}));
const AppBar = ({ config }) => {
@ -48,19 +57,20 @@ const AppBar = ({ config }) => {
return (
<>
<MuiAppBar position='fixed' elevation={0}>
<MuiAppBar position="fixed" elevation={0} color="primary">
<Toolbar>
<Link classes={{ root: classes.logoLink }} href='/'>
{/* <div className={classes.logo}>
<Link classes={{ root: classes.logoLink }} href="/">
<div className={classes.logo}>
<LaconicIcon />
</div> */}
<div className={classes.title}>
<Typography variant='h6'>Laconic</Typography>
</div>
</Link>
&nbsp;
<Divider
orientation="vertical"
flexItem
className={classes.divider}
/>
<div className={classes.title}>
<Typography variant='h6'>{config.app.title}</Typography>
<Typography variant="h6">{config.app.title}</Typography>
</div>
{/* <div>
<Link

View File

@ -2,24 +2,36 @@
// Copyright 2020 DXOS.org
//
import React from 'react';
import { makeStyles } from '@material-ui/core';
import React from "react";
import { makeStyles } from "@material-ui/core";
import { JsonTreeView } from '@lirewine/react-ux';
import { JsonTreeView } from "@lirewine/react-ux";
import { omitDeep } from '../util/omit';
import { omitDeep } from "../util/omit";
const useStyles = makeStyles(() => ({
root: {
flex: 1
}
flex: 1,
},
}));
const useTreeStyles = makeStyles(
(theme) => ({
colorPrimary: {
color: theme.palette.secondary.main,
},
}),
{ name: "MuiTypography" },
);
const Json = ({ data }) => {
const classes = useStyles();
useTreeStyles();
return (
<JsonTreeView className={classes.root} data={omitDeep(data, '__typename')} />
<JsonTreeView
className={classes.root}
data={omitDeep(data, "__typename")}
/>
);
};

View File

@ -5,7 +5,7 @@
import React from 'react';
import { makeStyles } from '@material-ui/core';
const useStyles = makeStyles(() => ({
const useStyles = makeStyles(theme => ({
root: {
display: 'flex',
flexDirection: 'column',
@ -17,7 +17,8 @@ const useStyles = makeStyles(() => ({
display: 'flex',
flexDirection: 'column',
flex: 1,
overflow: 'hidden'
overflow: 'hidden',
backgroundColor: theme.palette.background.paper,
}
}));

View File

@ -2,45 +2,60 @@
// Copyright 2020 DXOS.org
//
import clsx from 'clsx';
import React from 'react';
import { useHistory, useParams } from 'react-router';
import clsx from "clsx";
import React from "react";
import { useHistory, useParams } from "react-router";
// import { useQuery } from '@apollo/react-hooks';
import { makeStyles } from '@material-ui/core';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import LinkIcon from '@material-ui/icons/ExitToApp';
import ListItemText from '@material-ui/core/ListItemText';
import { makeStyles } from "@material-ui/core";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import LinkIcon from "@material-ui/icons/ExitToApp";
import ListItemText from "@material-ui/core/ListItemText";
// import EXTENSIONS from '../gql/extensions.graphql';
// import { useQueryStatusReducer } from '../hooks';
const useStyles = makeStyles(theme => ({
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
display: "flex",
flex: 1,
flexDirection: 'column',
justifyContent: 'space-between'
flexDirection: "column",
justifyContent: "space-between",
},
list: {
padding: 0
padding: 0,
},
listItem: {
display: "flex",
alignItems: "center",
backgroundColor: theme.palette.background.default,
},
selected: {
backgroundColor: theme.palette.background.secondary,
},
itemText: {
fontFamily: '"DM Mono", monospace',
fontWeight: 400,
},
icon: {
minWidth: 40,
color: theme.palette.grey[500]
color: theme.palette.grey[500],
},
selected: {
color: theme.palette.primary.main
color: theme.palette.text.primary,
},
expand: {
flex: 1
}
flex: 1,
},
}));
const Sidebar = ({ modules: { services, settings } }) => {
@ -52,38 +67,61 @@ const Sidebar = ({ modules: { services, settings } }) => {
// const extensions = extensionsData ? JSON.parse(extensionsData.extensions.json) : [];
const extensions = [];
const isSelected = path => path === `/${module}`;
const isSelected = (path) => path === `/${module}`;
const Modules = ({ modules }) => (
<List aria-label='items' className={classes.list}>
<List aria-label="items" className={classes.list}>
{modules.map(({ path, title, icon: Icon }) => (
<ListItem button selected={isSelected(path)} key={path} onClick={() => history.push(path)}>
<ListItem
button
selected={isSelected(path)}
key={path}
onClick={() => history.push(path)}
classes={{ root: classes.listItem, selected: classes.selected }}
>
<ListItemIcon classes={{ root: classes.icon }}>
<Icon className={clsx(classes.icon, isSelected(path) && classes.selected)} />
<Icon
className={clsx(
classes.icon,
isSelected(path) && classes.selected,
)}
/>
</ListItemIcon>
<ListItemText primary={title} />
<ListItemText
primary={title.toUpperCase()}
classes={{ primary: classes.itemText }}
/>
</ListItem>
))}
</List>
);
const Extensions = ({ extensions }) => (
<List aria-label='items' className={classes.list}>
<List aria-label="items" className={classes.list}>
{extensions.map(({ url, title }) => {
url = url
.replace('%HOST%', window.location.host)
.replace('%PORT%', window.location.port)
.replace('%PROTOCOL%', window.location.protocol);
.replace("%HOST%", window.location.host)
.replace("%PORT%", window.location.port)
.replace("%PROTOCOL%", window.location.protocol);
return (
<ListItem button key={url} onClick={() => { window.location = url; return true; }}>
<ListItem
button
key={url}
onClick={() => {
window.location = url;
return true;
}}
>
<ListItemIcon classes={{ root: classes.icon }}>
<LinkIcon className={clsx(classes.icon)} />
</ListItemIcon>
<ListItemText primary={title} />
<ListItemText
primary={title.toUpperCase()}
classes={{ primary: classes.itemText }}
/>
</ListItem>
);
}
)}
})}
</List>
);

View File

@ -2,20 +2,21 @@
// Copyright 2020 DXOS.org
//
import React from 'react';
import { makeStyles } from '@material-ui/core';
import MuiToolbar from '@material-ui/core/Toolbar';
import React from "react";
import { makeStyles } from "@material-ui/core";
import MuiToolbar from "@material-ui/core/Toolbar";
const useStyles = makeStyles(theme => ({
const useStyles = makeStyles((theme) => ({
toolbar: {
display: 'flex',
justifyContent: 'space-between',
whiteSpace: 'nowrap',
display: "flex",
justifyContent: "space-between",
whiteSpace: "nowrap",
'& > button': {
margin: theme.spacing(0.5)
}
}
"& > button": {
margin: theme.spacing(0.5),
},
color: "primary",
},
}));
// TODO(burdon): Tabs.

View File

@ -28,7 +28,10 @@ const useStyles = makeStyles((theme) => ({
flexDirection: 'row',
flex: 1,
justifyContent: 'space-between',
backgroundColor: grey[900],
backgroundColor: theme.palette.background.default,
borderTop: 1,
borderTopColor: "rgba(255, 255, 255, 0.12)",
borderTopStyle: "solid",
color: grey[400]
},
left: {

View File

@ -2,43 +2,48 @@
// Copyright 2020 DXOS.org
//
import React, { useState } from 'react';
import { makeStyles } from '@material-ui/core';
import Paper from '@material-ui/core/Paper';
import Tab from '@material-ui/core/Tab';
import Tabs from '@material-ui/core/Tabs';
import TabContext from '@material-ui/lab/TabContext';
import React, { useState } from "react";
import { makeStyles } from "@material-ui/core";
import Paper from "@material-ui/core/Paper";
import Tab from "@material-ui/core/Tab";
import Tabs from "@material-ui/core/Tabs";
import TabContext from "@material-ui/lab/TabContext";
import Panel from '../../../components/Panel';
import Toolbar from '../../../components/Toolbar';
import Panel from "../../../components/Panel";
import Toolbar from "../../../components/Toolbar";
// import LogPoller from '../../../components/LogPoller';
import RegistryLookup, { LookupType } from './RegistryLookup';
import RegistryStatus from './RegistryStatus';
import RegistryRecords from './RegistryRecords';
import RegistryLookup, { LookupType } from "./RegistryLookup";
import RegistryStatus from "./RegistryStatus";
import RegistryRecords from "./RegistryRecords";
// import RegistryRecords, { RecordType } from './RegistryRecords';
const TAB_RECORDS = 'records';
const TAB_STATUS = 'status';
const TAB_LOOKUP = 'lookup';
const TAB_RECORDS = "records";
const TAB_STATUS = "status";
const TAB_LOOKUP = "lookup";
// const TAB_LOG = 'log';
const useStyles = makeStyles(() => ({
expand: {
flex: 1
flex: 1,
},
panel: {
display: 'flex',
overflowY: 'scroll',
flex: 1
display: "flex",
overflowY: "scroll",
flex: 1,
},
paper: {
display: 'flex',
overflow: 'hidden',
flex: 1
}
display: "flex",
overflow: "hidden",
flex: 1,
},
tabs: {
fontFamily: '"DM Mono", monospace',
fontWeight: 400,
},
}));
const Registry = () => {
@ -51,10 +56,14 @@ const Registry = () => {
<Panel
toolbar={
<Toolbar>
<Tabs value={tab} onChange={(_, value) => setTab(value)}>
<Tab value={TAB_RECORDS} label='Records' />
<Tab value={TAB_LOOKUP} label='Lookup' />
<Tab value={TAB_STATUS} label='Status' />
<Tabs
value={tab}
onChange={(_, value) => setTab(value)}
indicatorColor="primary"
>
<Tab value={TAB_RECORDS} label="Records" className={classes.tabs} />
<Tab value={TAB_LOOKUP} label="Lookup" className={classes.tabs} />
<Tab value={TAB_STATUS} label="Status" className={classes.tabs} />
{/* <Tab value={TAB_LOG} label='Log' /> */}
</Tabs>

View File

@ -3,7 +3,7 @@
//
import moment from 'moment';
import React, { useContext } from 'react';
import React, { useContext, useState } from 'react';
import { useQuery } from '@apollo/react-hooks';
import { makeStyles } from '@material-ui/core';
import ButtonGroup from '@material-ui/core/ButtonGroup';
@ -11,6 +11,8 @@ import Button from '@material-ui/core/Button';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import TableBody from '@material-ui/core/TableBody';
import TablePagination from '@material-ui/core/TablePagination';
import { Paper, TableContainer, } from '@material-ui/core';
import WNS_RECORDS from '../../../gql/wns_records.graphql';
@ -68,9 +70,14 @@ export const RecordType = ({ type = types[0].key, onChange }) => {
const RegistryRecords = ({ type }) => {
const { config } = useContext(ConsoleContext);
const [sorter, sortBy] = useSorter('createTime', false);
const { data } = useQueryStatusReducer(useQuery(WNS_RECORDS, {
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10);
const offset = page * rowsPerPage;
const { data, refetch } = useQueryStatusReducer(useQuery(WNS_RECORDS, {
pollInterval: config.api.intervalQuery,
variables: { attributes: { type } }
variables: { attributes: { type, limit: rowsPerPage, offset: offset } }
}));
if (!data) {
@ -79,70 +86,100 @@ const RegistryRecords = ({ type }) => {
const records = JSON.parse(data.wns_records.json);
const handleChangePage = (event, newPage) => {
setPage(newPage);
const offset = newPage * rowsPerPage;
refetch({ attributes: { type, limit: rowsPerPage, offset } });
};
const handleChangeRowsPerPage = (event) => {
const newRowsPerPage = parseInt(event.target.value, 10);
setRowsPerPage(newRowsPerPage);
setPage(0);
refetch({ attributes: { type, limit: newRowsPerPage, offset: 0 } });
};
const labelDisplayedRows = ({ from, to }) => {
if (rowsPerPage > records.length) {
return `${from}-${from + records.length - 1}`;
} else {
return `${from}-${to}`;
}
};
return (
<Table>
<TableHead>
<TableRow>
<TableCell onClick={sortBy('attributes.type')} size='medium'>Type</TableCell>
<TableCell onClick={sortBy('names[0]')}>Registered Names</TableCell>
<TableCell onClick={sortBy('attributes.version')} size='small'>Version</TableCell>
<TableCell onClick={sortBy('attributes.name')}>Display Name</TableCell>
<TableCell onClick={sortBy('createTime')} size='small'>Created</TableCell>
<TableCell onClick={sortBy('attributes.package')}>Package</TableCell>
<TableCell size='icon' />
</TableRow>
</TableHead>
<TableBody>
{records.sort(sorter)
.map((record) => {
const { id, names, createTime, attributes: { type, name: displayName, fileName, version, description, service, package: pkg } } = record;
<Paper style={{
width: '100%',
}}>
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell onClick={sortBy('attributes.type')} size='medium'>Type</TableCell>
<TableCell onClick={sortBy('names[0]')}>Registered Names</TableCell>
<TableCell onClick={sortBy('attributes.version')} size='small'>Version</TableCell>
<TableCell onClick={sortBy('attributes.name')}>Display Name</TableCell>
<TableCell onClick={sortBy('createTime')} size='small'>Created</TableCell>
<TableCell onClick={sortBy('attributes.package')}>Package</TableCell>
<TableCell size='icon' />
</TableRow>
</TableHead>
<TableBody>
{records.sort(sorter).map((record) => {
const { id, names, createTime, attributes: { type, name: displayName, fileName, version, description, service, package: pkg } } = record;
let pkgLink;
let appLinks;
let pkgLink;
let appLinks;
if (pkg) {
pkgLink = (<PackageLink config={config} type={type} pkg={pkg} />);
}
if (pkg) {
pkgLink = (<PackageLink config={config} type={type} pkg={pkg} />);
}
if (type === 'lrn:app') {
appLinks = (
<>
{(names || []).map(lrn =>
<div key={lrn}>
<AppLink config={config} lrn={lrn} />
</div>
)}
</>
if (type === 'lrn:app') {
appLinks = (
<>
{(names || []).map(lrn =>
<div key={lrn}>
<AppLink config={config} lrn={lrn} />
</div>
)}
</>
);
}
return (
<TableRow key={id} size='small'>
<TableCell monospace>{type}</TableCell>
<TableCell monospace>
{appLinks || (names || []).map(name => <div key={name}>{name}</div>)}
</TableCell>
<TableCell monospace>{version}</TableCell>
<TableCell>{displayName || service || fileName || description}</TableCell>
<TableCell>{moment.utc(createTime).fromNow()}</TableCell>
<TableCell monospace>{pkgLink}</TableCell>
<TableCell>
<QueryLink config={config} id={id} icon />
</TableCell>
</TableRow>
);
}
return (
<TableRow key={id} size='small'>
<TableCell monospace>{type}</TableCell>
<TableCell monospace>
{appLinks || (names || []).map(name => <div key={name}>{name}</div>)}
</TableCell>
<TableCell monospace>
{version}
</TableCell>
<TableCell>
{displayName || service || fileName || description}
</TableCell>
<TableCell>
{moment.utc(createTime).fromNow()}
</TableCell>
<TableCell monospace>
{pkgLink}
</TableCell>
<TableCell>
<QueryLink config={config} id={id} icon />
</TableCell>
</TableRow>
);
}
)}
</TableBody>
</Table>
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
component="td"
rowsPerPageOptions={[5, 10, 25]}
count={-1}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
labelDisplayedRows={labelDisplayedRows}
nextIconButtonProps={{
disabled: records.length < rowsPerPage,
}}
/>
</Paper>
);
};

View File

@ -2,35 +2,47 @@
// Copyright 2020 DXOS.org
//
import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';
import React from "react";
import SvgIcon from "@material-ui/core/SvgIcon";
// TODO(burdon): Fixed color?
const Icon = (props) => (
<SvgIcon {...props} viewBox='0 0 256 256'>
<g transform='matrix(1,0,0,1,-160,-124)'>
<path
d='M282.254,147.134L195.254,194.589C191.399,196.692 189,200.732 189,205.124L189,298.876C189,303.268 191.399,307.308 195.254,309.411L282.254,356.866C285.836,358.819 290.164,358.819 293.746,356.866L380.746,309.411C384.601,307.308 387,303.268 387,298.876L387,205.124C387,200.732 384.601,196.692 380.746,194.589L293.746,147.134C290.164,145.181 285.836,145.181 282.254,147.134Z'
style={{ fill: 'none', fillRule: 'nonzero', stroke: 'rgb(0,68,121)', strokeWidth: '12px' }}
/>
<path
d='M288,252L216,216'
style={{ fill: 'none', fillRule: 'nonzero', stroke: 'rgb(0,68,121)', strokeWidth: '8px', strokeLinejoin: 'round' }}
/>
<path
d='M216,288L288,252'
style={{ fill: 'none', fillRule: 'nonzero', stroke: 'rgb(0,68,121)', strokeWidth: '8px', strokeLinejoin: 'round' }}
/>
<path
d='M360,288L288,252'
style={{ fill: 'none', fillRule: 'nonzero', stroke: 'rgb(0,68,121)', strokeWidth: '8px', strokeLinejoin: 'round' }}
/>
<path
d='M360,216L288,252'
style={{ fill: 'none', fillRule: 'nonzero', stroke: 'rgb(0,68,121)', strokeWidth: '8px', strokeLinejoin: 'round' }}
/>
</g>
<SvgIcon {...props} viewBox="0 0 115 20">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M3.37388 10.5194C5.70149 8.19185 7.14225 4.97748 7.1416 1.42853C7.14246 0.94681 7.11586 0.470456 7.063 0L-0.000488281 0.000643078L-0.000273922 13.5723C-0.000917354 15.2174 0.62632 16.863 1.88091 18.1175C3.1356 19.3721 4.78235 20.0001 6.42772 19.9993L6.42729 19.9997L19.9995 20L19.999 12.9355C19.5296 12.8838 19.0532 12.857 18.5704 12.8569C15.0224 12.8574 11.8079 14.298 9.48026 16.6255C7.78654 18.2768 5.07093 18.2771 3.39812 16.6043C1.72638 14.9325 1.72562 12.2161 3.37388 10.5194ZM18.5344 1.46863C16.5837 -0.481929 13.4146 -0.48268 11.4633 1.46863C9.512 3.41984 9.51276 6.58895 11.4633 8.53941C13.415 10.491 16.5831 10.4907 18.5344 8.53941C20.4857 6.5882 20.4861 3.42016 18.5344 1.46863Z"
fill="#FBFBFB"
/>
<path
d="M31.4741 18.5838H39.2552V16.3302H34.075V1.41351H31.4741V18.5838Z"
fill="#FBFBFB"
/>
<path
d="M49.8108 1.41351H45.4976L40.9893 18.5838H43.6769L44.8039 14.2913H50.3744L51.5014 18.5838H54.3191L49.8108 1.41351ZM45.3458 12.145L47.6 3.2593H47.6866L49.8541 12.145H45.3458Z"
fill="#FBFBFB"
/>
<path
d="M62.9292 8.06885H65.9636C65.9636 3.17534 64.3813 1.07196 60.6967 1.07196C56.8169 1.07196 55.1479 3.73341 55.1479 9.97909C55.1479 16.2462 56.8169 18.9291 60.6967 18.9291C64.3813 18.9291 65.9636 16.8901 65.9853 12.1468H62.9508C62.9292 15.8599 62.474 16.7828 60.6967 16.7828C58.6593 16.7828 58.1607 15.4307 58.1824 9.97909C58.1824 4.54896 58.6809 3.19678 60.6967 3.21823C62.474 3.21823 62.9292 4.18413 62.9292 8.06885Z"
fill="#FBFBFB"
/>
<path
d="M73.7781 1.07209C77.7229 1.09364 79.4135 3.77643 79.4135 10.0007C79.4135 16.2249 77.7229 18.9078 73.7781 18.9292C69.8117 18.9507 68.1211 16.2678 68.1211 10.0007C68.1211 3.73354 69.8117 1.05064 73.7781 1.07209ZM71.1555 10.0007C71.1555 15.4308 71.6757 16.783 73.7781 16.783C75.8589 16.783 76.3791 15.4308 76.3791 10.0007C76.3791 4.54909 75.8589 3.19691 73.7781 3.21847C71.6757 3.23992 71.1555 4.59209 71.1555 10.0007Z"
fill="#FBFBFB"
/>
<path
d="M85.0819 18.5624L82.481 18.5838V1.41351H87.0544L91.3243 15.4073H91.3676V1.41351H93.968V18.5838H89.677L85.1254 3.51689H85.0819V18.5624Z"
fill="#FBFBFB"
/>
<path
d="M100.468 1.41351H97.8677V18.5838H100.468V1.41351Z"
fill="#FBFBFB"
/>
<path
d="M111.139 8.06885H114.174C114.174 3.17534 112.591 1.07196 108.906 1.07196C105.028 1.07196 103.358 3.73341 103.358 9.97909C103.358 16.2462 105.028 18.9291 108.906 18.9291C112.591 18.9291 114.174 16.8901 114.195 12.1468H111.161C111.139 15.8599 110.684 16.7828 108.906 16.7828C106.869 16.7828 106.371 15.4307 106.393 9.97909C106.393 4.54896 106.891 3.19678 108.906 3.21823C110.684 3.21823 111.139 4.18413 111.139 8.06885Z"
fill="#FBFBFB"
/>
</SvgIcon>
);

View File

@ -45,7 +45,9 @@ export const createResolvers = config => {
wns_records: async (_, { attributes }) => {
log('WNS records...');
const data = await registry.queryRecords(attributes);
const {limit, offset, ...queryAttributes } = attributes || {};
const data = await registry.queryRecords(queryAttributes, false, false, limit, offset);
return {
__typename: 'JSONResult',

View File

@ -2,78 +2,96 @@
// Copyright 2019 DXOS.org
//
import { createTheme as createMuiTheme } from '@material-ui/core/styles';
import teal from '@material-ui/core/colors/teal';
import orange from '@material-ui/core/colors/orange';
import { createTheme as createMuiTheme } from "@material-ui/core/styles";
import teal from "@material-ui/core/colors/teal";
import orange from "@material-ui/core/colors/orange";
export const createTheme = (theme) => createMuiTheme({
export const createTheme = (theme) =>
createMuiTheme({
// https://material-ui.com/system/shadows
shadows: ["none"],
// https://material-ui.com/system/shadows
shadows: ['none'],
// https://stackoverflow.com/questions/60567673/reactjs-material-ui-theme-mixins-toolbar-offset-is-not-adapting-when-toolbar
mixins: {
denseToolbar: {
height: 48,
},
},
// https://stackoverflow.com/questions/60567673/reactjs-material-ui-theme-mixins-toolbar-offset-is-not-adapting-when-toolbar
mixins: {
denseToolbar: {
height: 48
}
},
// https://material-ui.com/customization/globals/#default-props
props: {
MuiButtonBase: {
disableRipple: true,
},
MuiButton: {
size: "small",
},
MuiFilledInput: {
margin: "dense",
},
MuiFormControl: {
margin: "dense",
},
MuiFormHelperText: {
margin: "dense",
},
MuiIconButton: {
size: "small",
},
MuiInputBase: {
margin: "dense",
},
MuiInputLabel: {
margin: "dense",
},
MuiTable: {
size: "small",
},
MuiTextField: {
margin: "dense",
},
MuiToolbar: {
variant: "dense",
},
},
// https://material-ui.com/customization/globals/#default-props
props: {
MuiButtonBase: {
disableRipple: true
},
MuiButton: {
size: 'small'
},
MuiFilledInput: {
margin: 'dense'
},
MuiFormControl: {
margin: 'dense'
},
MuiFormHelperText: {
margin: 'dense'
},
MuiIconButton: {
size: 'small'
},
MuiInputBase: {
margin: 'dense'
},
MuiInputLabel: {
margin: 'dense'
},
MuiTable: {
size: 'small'
},
MuiTextField: {
margin: 'dense'
},
MuiToolbar: {
variant: 'dense'
}
},
// https://material-ui.com/customization/palette/
palette:
theme === "dark"
? {
type: "dark",
primary: {
main: "#0000F4",
},
secondary: {
main: "#A2A2FF",
},
background: {
default: "#0F0F0F",
secondary: "#18181A",
paper: "#18181A",
},
text: {
primary: "#FBFBFB",
secondary: "#BDBCC3",
lineLabel: "#A2A2FF",
},
}
: {
primary: teal,
},
// https://material-ui.com/customization/palette/
palette: theme === 'dark' ? {
type: 'dark',
primary: orange
} : {
primary: teal
},
// https://material-ui.com/customization/theming/#theme-configuration-variables
// https://material-ui.com/customization/theming/#theme-configuration-variables
// https://material-ui.com/customization/globals/
overrides: {
MuiCssBaseline: {
'@global': {
body: {
margin: 0,
overflow: 'hidden'
}
}
}
}
});
// https://material-ui.com/customization/globals/
overrides: {
MuiCssBaseline: {
"@global": {
body: {
margin: 0,
overflow: "hidden",
},
},
},
},
});

View File

@ -14,6 +14,7 @@ module.exports = merge(commonConfig, {
// https://github.com/jantimon/html-webpack-plugin#options
new HtmlWebPackPlugin({
template: './public/index.html',
favicon: './public/favicon.ico',
templateParameters: {
title: 'Console'
}

View File

@ -1037,10 +1037,10 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@cerc-io/registry-sdk@^0.2.0":
version "0.2.0"
resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fregistry-sdk/-/0.2.0/registry-sdk-0.2.0.tgz#c14d5efb16bfd7ce288f67a8f2c521f28e5737ba"
integrity sha512-S7R/RfQwP6Im8s+k9kXA4PK8183ztypktYC/7vbYXpaKRkgEQ8J7rXL5trC2Rz1J4ghHsp/DYnyJNNqIILEDCw==
"@cerc-io/registry-sdk@^0.2.8":
version "0.2.8"
resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fregistry-sdk/-/0.2.8/registry-sdk-0.2.8.tgz#d71837f735d998987055068457fdf8b2e94ca69c"
integrity sha512-utK3Rq5qZrEoRs/eOsOkowcsD740nlnBs6C3KKFRHgKIiR0XedD6t33KukUPLKbGp4mYZOYXRTA7/A04x58lKw==
dependencies:
"@cosmjs/amino" "^0.28.1"
"@cosmjs/crypto" "^0.28.1"