Compare commits

..

1 Commits

Author SHA1 Message Date
Zach
c8d02c013f
Update package.json 2023-03-07 10:17:59 -05:00
120 changed files with 13721 additions and 5555 deletions

View File

@ -1,36 +0,0 @@
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

@ -1,39 +0,0 @@
name: Publish npm package to gitea
on:
release:
types: [published]
jobs:
npm_publish:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [ 18.x ]
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Download yarn
run: |
curl -fsSL -o /usr/local/bin/yarn https://github.com/yarnpkg/yarn/releases/download/v1.22.21/yarn-1.22.21.js
chmod +x /usr/local/bin/yarn
- name: Install jq
run: |
apt update && apt install -y jq
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: yarn
- name: Run yarn build
run: |
LACONIC_HOSTED_CONFIG_FILE=config-hosted.yml yarn dist
- name: Configure git.vdb.to npm registry
run: |
npm config set registry https://git.vdb.to/api/packages/cerc-io/npm/
- name: Authenticate to git.vdb.to registry
run: |
npm config set -- '//git.vdb.to/api/packages/cerc-io/npm/:_authToken' "${{ secrets.CICD_PUBLISH_TOKEN }}"
- name: npm publish
run: |
npm publish

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

12
.idea/console.iml generated Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,11 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
</profile>
</component>

6
.idea/jsLibraryMappings.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>

6
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="JSX" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/console.iml" filepath="$PROJECT_DIR$/.idea/console.iml" />
</modules>
</component>
</project>

12
.idea/runConfigurations/client.xml generated Normal file
View File

@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="client" type="js.build_tools.npm">
<package-json value="$PROJECT_DIR$/packages/console-app/package.json" />
<command value="run" />
<scripts>
<script value="start" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>

12
.idea/runConfigurations/server.xml generated Normal file
View File

@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="server" type="js.build_tools.npm">
<package-json value="$PROJECT_DIR$/packages/console-server/package.json" />
<command value="run" />
<scripts>
<script value="start" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

2
.npmrc Normal file
View File

@ -0,0 +1,2 @@
@cerc-io:registry=https://git.vdb.to/api/packages/cerc-io/npm/
@lirewine:registry=https://git.vdb.to/api/packages/cerc-io/npm/

View File

@ -1,27 +1,29 @@
# Console
Laconic console application.
Laconic Kubenet GraphQL server and console application.
User interface for submitting and reading records registered on Laconic.
![Console](./docs/images/console.png)
## Development
* Clone the required repos:
* [laconicd](https://git.vdb.to/cerc-io/laconicd)
* [laconicd](https://github.com/cerc-io/laconicd)
```bash
git clone git@git.vdb.to:cerc-io/laconicd.git
git clone git@github.com:cerc-io/laconicd.git
```
* Run the `laconicd` chain:
* In [laconicd](https://git.vdb.to/cerc-io/laconicd) repo, start the chain
* In [laconicd](https://github.com/cerc-io/laconicd) repo, start the chain
```bash
./scripts/init.sh clean
./init.sh
```
* Run the laconic-console app
* From the root of this repo, run:
* In [laconic-console](https://github.com/cerc-io/laconic-console) repo, install dependencies
```bash
yarn
@ -38,23 +40,27 @@ User interface for submitting and reading records registered on Laconic.
This can be ignored as it is an error for installing optional dependency
* Start the app:
* Change directory to [packages/console-app](https://github.com/cerc-io/laconic-console/tree/main/packages/console-app) and start the react app
```bash
# Change directory
cd packages/console-app/
# Start app
CONFIG_FILE=config-local.yml yarn start
```
* Open console at <http://localhost:8080>
* Open console-app at <http://localhost:8080>
* To view records in the console, the test suite in registry-sdk can be run
* To view records in the app, test suite in laconic-sdk can be run
* Clone the [registry-sdk](https://git.vdb.to/cerc-io/registry-sdk) repo:
* Clone the [laconic-sdk](https://github.com/cerc-io/laconic-sdk) repo:
```bash
git clone git@git.vdb.to:cerc-io/registry-sdk.git
git clone git@github.com:cerc-io/laconic-sdk.git
```
* In [registry-sdk](https://git.vdb.to/cerc-io/registry-sdk) repo, copy [.env.example](https://git.vdb.to/cerc-io/registry-sdk/blob/main/.env.example) file and create a `.env` file
* In [laconic-sdk](https://github.com/cerc-io/laconic-sdk) repo, copy [.env.example](https://github.com/cerc-io/laconic-sdk/blob/main/.env.example) file and create a `.env` file
```bash
cp .env.example .env
@ -63,7 +69,7 @@ User interface for submitting and reading records registered on Laconic.
* Export the private key using:
```bash
laconicd keys export alice --keyring-backend test --unarmored-hex --unsafe
laconicd keys export mykey --unarmored-hex --unsafe
```
* Copy the private key exported above and assign it to variable `PRIVATE_KEY` in the `.env` file.
@ -74,12 +80,12 @@ User interface for submitting and reading records registered on Laconic.
yarn
```
* Run the tests in registry-sdk repo:
* Run the tests in laconic-sdk repo:
```bash
yarn test
```
*NOTE*: One test from [util.test.ts](https://git.vdb.to/cerc-io/registry-sdk/blob/main/src/util.test.ts) fails as mentioned in the [PR](https://git.vdb.to/cerc-io/registry-sdk/pull/5#issuecomment-1299572012)
*NOTE*: One test from [util.test.ts](https://github.com/cerc-io/laconic-sdk/blob/main/src/util.test.ts) fails as mentioned in the [PR](https://github.com/cerc-io/laconic-sdk/pull/5#issuecomment-1299572012)
* Open console at <http://localhost:8080> to view the records.
* Open console-app at <http://localhost:8080> to view the records.

View File

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

View File

@ -1,42 +0,0 @@
#
# NODE_ENV=development
# NOTE: Set CONFIG_FILE to swap out this config file.
#
# TODO: write a tool to automated insertion of the template strings in files like this.
app:
title: 'Console'
org': 'Laconic'
theme: 'dark'
website: 'LACONIC_HOSTED_CONFIG_app_website' # e.g. https://laconic.com
publicUrl: '/console'
api:
server: 'LACONIC_HOSTED_CONFIG_api_server' # e.g. http://127.0.0.1:9004
path: '/api'
intervalLog: 5000
pollInterval: 10000
system:
debug: 'laconic:console:*'
services:
app:
prefix: '/app'
server: 'LACONIC_HOSTED_CONFIG_services_app_server' # e.g. http://127.0.0.1:5999
wns:
server: 'LACONIC_HOSTED_CONFIG_services_wns_server' # e.g. http://127.0.0.1:9473/api
webui: 'LACONIC_HOSTED_CONFIG_services_wns_webui' # e.g. http://127.0.0.1:9473/console
signal:
server: 'LACONIC_HOSTED_CONFIG_services_signal_server' # e.g. ws://127.0.0.1:4000
api: 'LACONIC_HOSTED_CONFIG_services_signal_api' # e.g. http://127.0.0.1:4000/api
ipfs:
server: 'LACONIC_HOSTED_CONFIG_services_ipfs_server' # e.g. http://127.0.0.1:5001
gateway: 'LACONIC_HOSTED_CONFIG_services_ipfs_gateway' # e.g. http://127.0.0.1:8888/ipfs/
wellknown:
endpoint: 'LACONIC_HOSTED_CONFIG_services_wellknown_endpoint' # e.g. http://127.0.0.1:9000/.well-known/laconic

BIN
docs/images/console.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 KiB

5
lerna.json Normal file
View File

@ -0,0 +1,5 @@
{
"version": "1.2.9",
"useWorkspaces": true,
"npmClient": "yarn"
}

View File

@ -1,91 +1,69 @@
{
"name": "@cerc-io/console-app",
"version": "0.2.5",
"name": "laconic-console",
"version": "1.2.9-alpha.0",
"description": "Laconic Console",
"repository": "https://github.com/cerc-io/laconic-console",
"main": "dist/es/index.js",
"files": [
"dist/*", "src/*"
],
"main": "index.js",
"private": true,
"scripts": {
"analyzer": "webpack --config webpack-analyzer.config.js",
"build": "yarn dist",
"build:babel": "babel ./src --out-dir ./dist/es --ignore \"**/*.test.js\" --source-maps inline",
"clean": "rm -rf dist",
"updatever": "scripts/update_version.sh > src/version.json",
"dist": "yarn clean && yarn updatever && yarn build:babel && CONFIG_FILE=${LACONIC_HOSTED_CONFIG_FILE:-config-production.yml} webpack",
"lint": "semistandard 'src/**/*.js'",
"start": "CONFIG_FILE=${CONFIG_FILE:-config-testnet.yml} VERBOSE=true webpack-dev-server --mode development",
"test": "jest --rootDir ./src --passWithNoTests --no-cache"
"build": "lerna run build",
"clean": "lerna run clean",
"lint": "lerna run lint",
"lint:fix": "lerna run lint -- --fix",
"lint:staged": "lint-staged",
"sort-package-json": "lerna exec npx sort-package-json",
"test": "lerna run test"
},
"author": "",
"license": "GPL-3.0",
"license": "AGPLv3",
"workspaces": {
"packages": [
"packages/*"
]
},
"browserslist": [
"> 2%"
"> 5%"
],
"jest": {
"testEnvironment": "node"
},
"dependencies": {
"@apollo/client": "^3.7.10",
"@apollo/react-components": "^4.0.0",
"@apollo/react-hooks": "^4.0.0",
"@babel/runtime": "^7.21.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",
"@material-ui/core": "^4.12.4",
"@material-ui/icons": "^4.11.3",
"@material-ui/lab": "^4.0.0-alpha.61",
"@rehooks/component-size": "^1.0.3",
"@visx/network": "^1.0.0",
"@visx/tooltip": "^1.0.0",
"@visx/zoom": "^1.0.0",
"build-url": "^2.0.0",
"clsx": "^1.1.0",
"compare-versions": "^3.6.0",
"d3-force": "^2.1.1",
"debug": "^4.1.1",
"graphql-tag": "^2.10.3",
"lodash.defaultsdeep": "^4.6.1",
"lodash.get": "^4.4.2",
"moment": "^2.26.0",
"node-polyfill-webpack-plugin": "^2.0.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-router": "^5.3.4",
"react-router-dom": "^5.3.4",
"source-map-support": "^0.5.12"
"lerna": "^3.19.0"
},
"devDependencies": {
"@babel/cli": "7.21.0",
"@babel/core": "^7.21.0",
"@babel/preset-env": "^7.20.2",
"@babel/preset-react": "^7.18.6",
"@webpack-cli/info": "^2.0.1",
"babel-jest": "^29.5.0",
"babel-loader": "^9.1.2",
"babel-plugin-import-graphql": "^2.7.0",
"babel-plugin-inline-import": "^3.0.0",
"babel-plugin-inline-json-import": "^0.3.2",
"dotenv-webpack": "^8.0.1",
"graphql": "^15.0.0",
"html-webpack-plugin": "^5.5.0",
"jest": "^29.5.0",
"webpack": "^5.76.2",
"webpack-bundle-analyzer": "^4.8.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.13.1",
"webpack-merge": "^5.8.0",
"webpack-version-file-plugin": "^0.5.0",
"yaml-loader": "^0.8.0"
"babel-eslint": "^10.0.3",
"eslint": "^6.7.2",
"eslint-config-semistandard": "^15.0.0",
"eslint-config-standard": "^14.1.1",
"eslint-loader": "^3.0.3",
"eslint-plugin-babel": "^5.3.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jest": "^23.13.1",
"eslint-plugin-jsdoc": "^21.0.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-standard": "^4.0.1",
"lint-staged": "^9.5.0",
"pre-commit": "^1.2.2",
"webpack-cli": "^3.3.11"
},
"peerDependencies": {
"react": "16.12.0",
"react-dom": "^16.12.0"
"eslintConfig": {
"parser": "babel-eslint",
"extends": [
"plugin:jest/recommended",
"semistandard"
],
"plugins": [
"babel"
],
"rules": {
"babel/semi": 1
}
},
"publishConfig": {
"access": "public"
"semistandard": {
"parser": "babel-eslint",
"env": [
"jest",
"node",
"browser"
]
}
}

View File

@ -0,0 +1,58 @@
# Console
Apollo GraphQL client.
## Usage
First start the server:
```bash
cd packages/console-server
yarn start
```
Then start the Webpack devserver.
```bash
cd packages/console-app
yarn start
```
Then load the app: http://localhost:8080.
## Using a KUBE
To use your KUBE for testing, rather than running all the services locally, specify a different
config file when starting: `config-kube.yml`, which connects to `kube.local` for all services.
For example:
```javascript
cd packages/console-app
CONFIG_FILE=config-kube.yml yarn start
```
## Deploy
```bash
yarn build
```
This creates the following folders:
```
/dist
/es # Module imports.
/production # Production build.
```
NOTE: GQL and Production files and exported and may be used by the server.
```javascript
import SYSTEM_STATUS from '@cerc-io/console-app/src/gql/system_status.graphql';
...
const file = path.join(__dirname + '../../../../node_modules/@cerc-io/console-app/dist/production', 'index.html');
res.sendFile(file);
```

View File

@ -12,6 +12,7 @@ module.exports = {
'import-graphql',
'inline-json-import',
'@babel/plugin-proposal-class-properties'
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-export-default-from'
]
};

View File

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

View File

@ -0,0 +1,133 @@
{
"name": "@cerc-io/console-app",
"version": "1.2.9",
"description": "Kubenet Console Client",
"repository": "https://github.com/cerc-io/laconic-console",
"main": "dist/es/index.js",
"files": [
"src/gql"
],
"scripts": {
"analyzer": "webpack --config webpack-analyzer.config.js",
"build": "yarn dist",
"build:babel": "babel ./src --out-dir ./dist/es --ignore \"**/*.test.js\" --source-maps inline",
"clean": "rm -rf dist",
"dist": "yarn clean && yarn build:babel && CONFIG_FILE=config-production.yml webpack",
"lint": "semistandard 'src/**/*.js'",
"start": "CONFIG_FILE=${CONFIG_FILE:-config-testnet.yml} VERBOSE=true webpack-dev-server --host 0.0.0.0 --mode development",
"test": "jest --rootDir ./src --passWithNoTests --no-cache"
},
"author": "",
"license": "GPL-3.0",
"browserslist": [
"> 2%"
],
"jest": {
"testEnvironment": "node"
},
"dependencies": {
"@apollo/react-components": "^3.1.5",
"@apollo/react-hooks": "^3.1.5",
"@babel/runtime": "^7.8.7",
"@cerc-io/laconic-sdk": "0.1.4",
"@lirewine/debug": "1.0.0-beta.78",
"@lirewine/gem-core": "1.0.0-beta.28",
"@lirewine/react-ux": "1.1.0-beta.0",
"@material-ui/core": "^4.10.0",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.54",
"@rehooks/component-size": "^1.0.3",
"@visx/network": "^1.0.0",
"@visx/tooltip": "^1.0.0",
"@visx/zoom": "^1.0.0",
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "^2.6.10",
"apollo-link": "^1.2.14",
"apollo-link-http": "^1.5.17",
"build-url": "^2.0.0",
"clsx": "^1.1.0",
"compare-versions": "^3.6.0",
"d3-force": "^2.1.1",
"debug": "^4.1.1",
"graphql-tag": "^2.10.3",
"lodash.defaultsdeep": "^4.6.1",
"lodash.get": "^4.4.2",
"moment": "^2.26.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"source-map-support": "^0.5.12"
},
"devDependencies": {
"@babel/cli": "7.4.4",
"@babel/core": "^7.4.5",
"@babel/node": "^7.8.7",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-proposal-export-default-from": "^7.8.3",
"@babel/preset-env": "^7.4.5",
"@babel/preset-react": "^7.0.0",
"@webpack-cli/info": "^0.2.0",
"@webpack-cli/init": "^0.3.0",
"babel-eslint": "^10.0.2",
"babel-jest": "^24.8.0",
"babel-loader": "^8.0.0",
"babel-plugin-add-module-exports": "^1.0.2",
"babel-plugin-import-graphql": "^2.7.0",
"babel-plugin-inline-import": "^3.0.0",
"babel-plugin-inline-json-import": "^0.3.2",
"dotenv-webpack": "^1.8.0",
"eslint": "^6.7.2",
"eslint-config-semistandard": "^15.0.0",
"eslint-config-standard": "^14.1.1",
"eslint-config-standard-jsx": "^8.1.0",
"eslint-loader": "^3.0.3",
"eslint-plugin-babel": "^5.3.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jest": "^23.13.1",
"eslint-plugin-jsdoc": "^21.0.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-standard": "^4.0.1",
"graphql": "^15.0.0",
"html-webpack-plugin": "^4.3.0",
"jest": "^24.8.0",
"react-scripts": "^3.4.1",
"semistandard": "^14.2.0",
"webpack": "^4.41.2",
"webpack-bundle-analyzer": "^3.6.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "^4.2.2",
"webpack-version-file-plugin": "^0.4.0",
"yaml-loader": "^0.6.0"
},
"peerDependencies": {
"react": "16.12.0",
"react-dom": "^16.12.0"
},
"publishConfig": {
"access": "public"
},
"eslintConfig": {
"parser": "babel-eslint",
"extends": [
"plugin:jest/recommended",
"semistandard",
"standard-jsx"
],
"plugins": [
"babel"
],
"rules": {
"babel/semi": 1
}
},
"semistandard": {
"parser": "babel-eslint",
"env": [
"jest",
"node",
"browser"
]
}
}

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><%= title %></title>
</head>
<body>
<div id="root"></div>
</body>
</html>

View File

@ -2,7 +2,10 @@
// Copyright 2020 DXOS.org
//
import { ApolloClient, InMemoryCache, ApolloLink, HttpLink } from '@apollo/client';
import { ApolloClient } from 'apollo-client';
import { ApolloLink } from 'apollo-link';
import { createHttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { createResolvers } from './resolvers';
import { getServiceUrl } from './util/config';
@ -25,7 +28,7 @@ export const graphqlApi = config => {
*/
export const clientFactory = config => {
// https://www.apollographql.com/docs/link/
const defaultLink = new HttpLink({
const defaultLink = createHttpLink({
uri: graphqlApi(config),
// TODO(burdon): Authentication: send signed message to server (from client wallet).
@ -36,7 +39,7 @@ export const clientFactory = config => {
});
const serviceLinks = {
signal: new HttpLink({
signal: createHttpLink({
uri: getServiceUrl(config, 'signal.api')
})
};

View File

@ -0,0 +1,84 @@
//
// 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 GraphQLIcon from '@material-ui/icons/Adb';
// import LaconicIcon from '../icons/Laconic';
// import { graphqlApi } from '../client';
const useStyles = makeStyles((theme) => ({
offset: theme.mixins.denseToolbar,
logo: {
marginRight: theme.spacing(2),
color: theme.palette.grey[800],
'& svg': {
width: 100,
height: 48
}
},
logoLink: {
lineHeight: 0
},
title: {
display: 'flex',
flex: 1,
marginTop: 2,
color: theme.palette.grey[800]
},
link: {
color: blueGrey[900]
}
}));
const AppBar = ({ config }) => {
const classes = useStyles();
return (
<>
<MuiAppBar position='fixed' elevation={0}>
<Toolbar>
<Link classes={{ root: classes.logoLink }} href='/'>
{/* <div className={classes.logo}>
<LaconicIcon />
</div> */}
<div className={classes.title}>
<Typography variant='h6'>Laconic</Typography>
</div>
</Link>
&nbsp;
<div className={classes.title}>
<Typography variant='h6'>{config.app.title}</Typography>
</div>
{/* <div>
<Link
className={classes.link}
href={graphqlApi(config)}
rel='noreferrer'
target='_blank'
title='Console GraphQL'
>
<GraphQLIcon />
</Link>
</div> */}
</Toolbar>
</MuiAppBar>
<div className={classes.offset} />
</>
);
};
export default AppBar;

View File

@ -31,9 +31,9 @@ const getAppUrl = (config, { wrn }) => {
* @param {string} name
* @param {string} [text]
*/
const AppLink = ({ config, lrn, text }) => {
const fullURL = getAppUrl(config, { lrn });
return <Link href={fullURL} target={lrn}>{text || lrn}</Link>;
const AppLink = ({ config, crn, text }) => {
const fullURL = getAppUrl(config, { crn });
return <Link href={fullURL} target={crn}>{text || crn}</Link>;
};
export default AppLink;

View File

@ -0,0 +1,26 @@
//
// Copyright 2020 DXOS.org
//
import React from 'react';
import { makeStyles } from '@material-ui/core';
import { JsonTreeView } from '@lirewine/react-ux';
import { omitDeep } from '../util/omit';
const useStyles = makeStyles(() => ({
root: {
flex: 1
}
}));
const Json = ({ data }) => {
const classes = useStyles();
return (
<JsonTreeView className={classes.root} data={omitDeep(data, '__typename')} />
);
};
export default Json;

View File

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

View File

@ -10,41 +10,8 @@ import LinkIcon from '@material-ui/icons/ExitToApp';
import { getServiceUrl } from '../util/config';
const QUERY = `
fragment ValueParts on Value {
... on BooleanValue {
bool: value
}
... on IntValue {
int: value
}
... on FloatValue {
float: value
}
... on StringValue {
string: value
}
... on BytesValue {
bytes: value
}
... on LinkValue {
link: value
}
}
fragment AttrParts on Attribute {
key
value {
...ValueParts
... on ArrayValue {
value {
...ValueParts
}
}
}
}
{
getRecordsByIds(ids: ["%ID%"]) {
query {
getRecordsByIds(ids: [ "%ID%" ]) {
id
names
bondId
@ -52,12 +19,12 @@ const QUERY = `
expiryTime
owners
attributes {
...AttrParts
key
value {
... on MapValue {
map: value {
...AttrParts
}
string
json
reference {
id
}
}
}

View File

@ -0,0 +1,100 @@
//
// Copyright 2020 DXOS.org
//
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 EXTENSIONS from '../gql/extensions.graphql';
// import { useQueryStatusReducer } from '../hooks';
const useStyles = makeStyles(theme => ({
root: {
display: 'flex',
flex: 1,
flexDirection: 'column',
justifyContent: 'space-between'
},
list: {
padding: 0
},
icon: {
minWidth: 40,
color: theme.palette.grey[500]
},
selected: {
color: theme.palette.primary.main
},
expand: {
flex: 1
}
}));
const Sidebar = ({ modules: { services, settings } }) => {
const classes = useStyles();
const history = useHistory();
const { module } = useParams();
// const { data: extensionsData } = useQueryStatusReducer(useQuery(EXTENSIONS));
// const extensions = extensionsData ? JSON.parse(extensionsData.extensions.json) : [];
const extensions = [];
const isSelected = path => path === `/${module}`;
const Modules = ({ modules }) => (
<List aria-label='items' className={classes.list}>
{modules.map(({ path, title, icon: Icon }) => (
<ListItem button selected={isSelected(path)} key={path} onClick={() => history.push(path)}>
<ListItemIcon classes={{ root: classes.icon }}>
<Icon className={clsx(classes.icon, isSelected(path) && classes.selected)} />
</ListItemIcon>
<ListItemText primary={title} />
</ListItem>
))}
</List>
);
const Extensions = ({ extensions }) => (
<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);
return (
<ListItem button key={url} onClick={() => { window.location = url; return true; }}>
<ListItemIcon classes={{ root: classes.icon }}>
<LinkIcon className={clsx(classes.icon)} />
</ListItemIcon>
<ListItemText primary={title} />
</ListItem>
);
}
)}
</List>
);
return (
<div className={classes.root}>
<Modules modules={services} />
<Extensions extensions={extensions} />
<div className={classes.expand} />
<Modules modules={settings} />
</div>
);
};
export default Sidebar;

View File

@ -0,0 +1,32 @@
//
// Copyright 2020 DXOS.org
//
import React from 'react';
import { makeStyles } from '@material-ui/core';
import MuiToolbar from '@material-ui/core/Toolbar';
const useStyles = makeStyles(theme => ({
toolbar: {
display: 'flex',
justifyContent: 'space-between',
whiteSpace: 'nowrap',
'& > button': {
margin: theme.spacing(0.5)
}
}
}));
// TODO(burdon): Tabs.
const Toolbar = ({ children }) => {
const classes = useStyles();
return (
<MuiToolbar disableGutters className={classes.toolbar}>
{children}
</MuiToolbar>
);
};
export default Toolbar;

View File

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

View File

@ -2,48 +2,43 @@
// 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,
},
tabs: {
fontFamily: '"DM Mono", monospace',
fontWeight: 400,
},
display: 'flex',
overflow: 'hidden',
flex: 1
}
}));
const Registry = () => {
@ -56,14 +51,10 @@ const Registry = () => {
<Panel
toolbar={
<Toolbar>
<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} />
<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' />
{/* <Tab value={TAB_LOG} label='Log' /> */}
</Tabs>

View File

@ -37,7 +37,7 @@ const useStyles = makeStyles(theme => ({
const types = [
{ key: 'authority', label: 'Authority' },
{ key: 'lrn', label: 'LRN' }
{ key: 'crn', label: 'CRN' }
];
export const LookupType = ({ scope = types[0].key, onChange }) => {
@ -87,7 +87,7 @@ const RegistryLookup = ({ scope }) => {
const getNames = () => {
let ret;
switch (scope) {
case 'lrn': {
case 'crn': {
ret = [];
records.forEach(item => ret.push(...(item.names || [])));
break;
@ -99,8 +99,8 @@ const RegistryLookup = ({ scope }) => {
const names = new Set();
for (const record of records) {
for (const name of (record.names || [])) {
// TODO(telackey): We need a general purpose LRN handling library.
names.add(name.replace('lrn://', '').split('/')[0]);
// TODO(telackey): We need a general purpose CRN handling library.
names.add(name.replace('crn://', '').split('/')[0]);
}
}
ret = Array.from(names.values());
@ -120,7 +120,7 @@ const RegistryLookup = ({ scope }) => {
let result;
switch (scope) {
case 'lrn':
case 'crn':
result = await registry.lookupNames([newInputValue], true);
break;

View File

@ -0,0 +1,149 @@
//
// Copyright 2020 DXOS.org
//
import moment from 'moment';
import React, { useContext } from 'react';
import { useQuery } from '@apollo/react-hooks';
import { makeStyles } from '@material-ui/core';
import ButtonGroup from '@material-ui/core/ButtonGroup';
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 WNS_RECORDS from '../../../gql/wns_records.graphql';
import { ConsoleContext, useQueryStatusReducer, useSorter } from '../../../hooks';
import Table from '../../../components/Table';
import TableCell from '../../../components/TableCell';
import PackageLink from '../../../components/PackageLink';
import QueryLink from '../../../components/QueryLink';
import AppLink from '../../../components/AppLink';
const useStyles = makeStyles(theme => ({
selected: {
color: theme.palette.text.primary
}
}));
const types = [
{ key: null, label: 'ALL' },
{ key: 'crn:kube', label: 'Kube' },
{ key: 'crn:service', label: 'Service' },
{ key: 'crn:app', label: 'App' },
{ key: 'crn:bot', label: 'Bot' },
{ key: 'crn:bot-factory', label: 'Bot Factory' },
{ key: 'crn:file', label: 'File' },
{ key: 'crn:type', label: 'Type' }
];
export const RecordType = ({ type = types[0].key, onChange }) => {
const classes = useStyles();
return (
<ButtonGroup
disableRipple
disableFocusRipple
variant='outlined'
color='primary'
size='small'
aria-label='text primary button group'
>
{types.map(t => (
<Button
key={t.key}
className={t.key === type && classes.selected}
onClick={() => onChange(t.key)}
>
{t.label}
</Button>
))}
</ButtonGroup>
);
};
const RegistryRecords = ({ type }) => {
const { config } = useContext(ConsoleContext);
const [sorter, sortBy] = useSorter('createTime', false);
const { data } = useQueryStatusReducer(useQuery(WNS_RECORDS, {
pollInterval: config.api.intervalQuery,
variables: { attributes: { type } }
}));
if (!data) {
return null;
}
const records = JSON.parse(data.wns_records.json);
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;
let pkgLink;
let appLinks;
if (pkg) {
pkgLink = (<PackageLink config={config} type={type} pkg={pkg} />);
}
if (type === 'crn:app') {
appLinks = (
<>
{(names || []).map(crn =>
<div key={crn}>
<AppLink config={config} crn={crn} />
</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>
);
}
)}
</TableBody>
</Table>
);
};
export default RegistryRecords;

View File

@ -2,7 +2,7 @@
// Copyright 2020 DXOS.org
//
import { Registry } from '@cerc-io/registry-sdk';
import { Registry } from '@cerc-io/laconic-sdk';
import { getServiceUrl } from '../util/config';

View File

@ -0,0 +1,37 @@
//
// Copyright 2020 DXOS.org
//
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>
);
export default Icon;

View File

@ -4,7 +4,7 @@
import debug from 'debug';
import { Registry } from '@cerc-io/registry-sdk';
import { Registry } from '@cerc-io/laconic-sdk';
import { getServiceUrl } from './util/config';
@ -45,9 +45,7 @@ export const createResolvers = config => {
wns_records: async (_, { attributes }) => {
log('WNS records...');
const {limit, offset, ...queryAttributes } = attributes || {};
const data = await registry.queryRecords(queryAttributes, false, false, limit, offset);
const data = await registry.queryRecords(attributes);
return {
__typename: 'JSONResult',

View File

@ -0,0 +1,79 @@
//
// 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';
export const createTheme = (theme) => createMuiTheme({
// 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://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: orange
} : {
primary: teal
},
// https://material-ui.com/customization/theming/#theme-configuration-variables
// https://material-ui.com/customization/globals/
overrides: {
MuiCssBaseline: {
'@global': {
body: {
margin: 0,
overflow: 'hidden'
}
}
}
}
});

View File

@ -0,0 +1,7 @@
{
"build": {
"name": "@cerc-io/console-app",
"buildDate": "2020-12-19T03:06:08.492Z",
"version": "1.2.9-alpha.1"
}
}

Some files were not shown because too many files have changed in this diff Show More