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 # Console
Laconic console application. Laconic Kubenet GraphQL server and console application.
User interface for submitting and reading records registered on Laconic. User interface for submitting and reading records registered on Laconic.
![Console](./docs/images/console.png)
## Development ## Development
* Clone the required repos: * Clone the required repos:
* [laconicd](https://git.vdb.to/cerc-io/laconicd) * [laconicd](https://github.com/cerc-io/laconicd)
```bash ```bash
git clone git@git.vdb.to:cerc-io/laconicd.git git clone git@github.com:cerc-io/laconicd.git
``` ```
* Run the `laconicd` chain: * 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 ```bash
./scripts/init.sh clean ./init.sh
``` ```
* Run the laconic-console app * 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 ```bash
yarn 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 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 ```bash
# Change directory
cd packages/console-app/
# Start app
CONFIG_FILE=config-local.yml yarn start 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 ```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 ```bash
cp .env.example .env cp .env.example .env
@ -63,7 +69,7 @@ User interface for submitting and reading records registered on Laconic.
* Export the private key using: * Export the private key using:
```bash ```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. * 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 yarn
``` ```
* Run the tests in registry-sdk repo: * Run the tests in laconic-sdk repo:
```bash ```bash
yarn test 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", "name": "laconic-console",
"version": "0.2.5", "version": "1.2.9-alpha.0",
"description": "Laconic Console", "description": "Laconic Console",
"repository": "https://github.com/cerc-io/laconic-console", "main": "index.js",
"main": "dist/es/index.js", "private": true,
"files": [
"dist/*", "src/*"
],
"scripts": { "scripts": {
"analyzer": "webpack --config webpack-analyzer.config.js", "build": "lerna run build",
"build": "yarn dist", "clean": "lerna run clean",
"build:babel": "babel ./src --out-dir ./dist/es --ignore \"**/*.test.js\" --source-maps inline", "lint": "lerna run lint",
"clean": "rm -rf dist", "lint:fix": "lerna run lint -- --fix",
"updatever": "scripts/update_version.sh > src/version.json", "lint:staged": "lint-staged",
"dist": "yarn clean && yarn updatever && yarn build:babel && CONFIG_FILE=${LACONIC_HOSTED_CONFIG_FILE:-config-production.yml} webpack", "sort-package-json": "lerna exec npx sort-package-json",
"lint": "semistandard 'src/**/*.js'", "test": "lerna run test"
"start": "CONFIG_FILE=${CONFIG_FILE:-config-testnet.yml} VERBOSE=true webpack-dev-server --mode development",
"test": "jest --rootDir ./src --passWithNoTests --no-cache"
}, },
"author": "", "author": "",
"license": "GPL-3.0", "license": "AGPLv3",
"workspaces": {
"packages": [
"packages/*"
]
},
"browserslist": [ "browserslist": [
"> 2%" "> 5%"
], ],
"jest": { "jest": {
"testEnvironment": "node" "testEnvironment": "node"
}, },
"dependencies": { "dependencies": {
"@apollo/client": "^3.7.10", "lerna": "^3.19.0"
"@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"
}, },
"devDependencies": { "devDependencies": {
"@babel/cli": "7.21.0", "babel-eslint": "^10.0.3",
"@babel/core": "^7.21.0", "eslint": "^6.7.2",
"@babel/preset-env": "^7.20.2", "eslint-config-semistandard": "^15.0.0",
"@babel/preset-react": "^7.18.6", "eslint-config-standard": "^14.1.1",
"@webpack-cli/info": "^2.0.1", "eslint-loader": "^3.0.3",
"babel-jest": "^29.5.0", "eslint-plugin-babel": "^5.3.0",
"babel-loader": "^9.1.2", "eslint-plugin-import": "^2.18.2",
"babel-plugin-import-graphql": "^2.7.0", "eslint-plugin-jest": "^23.13.1",
"babel-plugin-inline-import": "^3.0.0", "eslint-plugin-jsdoc": "^21.0.0",
"babel-plugin-inline-json-import": "^0.3.2", "eslint-plugin-node": "^11.1.0",
"dotenv-webpack": "^8.0.1", "eslint-plugin-standard": "^4.0.1",
"graphql": "^15.0.0", "lint-staged": "^9.5.0",
"html-webpack-plugin": "^5.5.0", "pre-commit": "^1.2.2",
"jest": "^29.5.0", "webpack-cli": "^3.3.11"
"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"
}, },
"peerDependencies": { "eslintConfig": {
"react": "16.12.0", "parser": "babel-eslint",
"react-dom": "^16.12.0" "extends": [
"plugin:jest/recommended",
"semistandard"
],
"plugins": [
"babel"
],
"rules": {
"babel/semi": 1
}
}, },
"publishConfig": { "semistandard": {
"access": "public" "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', 'import-graphql',
'inline-json-import', '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: app:
title: 'Console' title: 'Console'
org: 'Laconic' org': 'Laconic'
theme: 'dark' theme: 'dark'
website: 'https://laconic.com' website: 'https://laconic.com'
publicUrl: '/console' 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 // 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 { createResolvers } from './resolvers';
import { getServiceUrl } from './util/config'; import { getServiceUrl } from './util/config';
@ -25,7 +28,7 @@ export const graphqlApi = config => {
*/ */
export const clientFactory = config => { export const clientFactory = config => {
// https://www.apollographql.com/docs/link/ // https://www.apollographql.com/docs/link/
const defaultLink = new HttpLink({ const defaultLink = createHttpLink({
uri: graphqlApi(config), uri: graphqlApi(config),
// TODO(burdon): Authentication: send signed message to server (from client wallet). // TODO(burdon): Authentication: send signed message to server (from client wallet).
@ -36,7 +39,7 @@ export const clientFactory = config => {
}); });
const serviceLinks = { const serviceLinks = {
signal: new HttpLink({ signal: createHttpLink({
uri: getServiceUrl(config, 'signal.api') 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} name
* @param {string} [text] * @param {string} [text]
*/ */
const AppLink = ({ config, lrn, text }) => { const AppLink = ({ config, crn, text }) => {
const fullURL = getAppUrl(config, { lrn }); const fullURL = getAppUrl(config, { crn });
return <Link href={fullURL} target={lrn}>{text || lrn}</Link>; return <Link href={fullURL} target={crn}>{text || crn}</Link>;
}; };
export default AppLink; 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 React from 'react';
import { makeStyles } from '@material-ui/core'; import { makeStyles } from '@material-ui/core';
const useStyles = makeStyles(theme => ({ const useStyles = makeStyles(() => ({
root: { root: {
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
@ -17,8 +17,7 @@ const useStyles = makeStyles(theme => ({
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
flex: 1, flex: 1,
overflow: 'hidden', overflow: 'hidden'
backgroundColor: theme.palette.background.paper,
} }
})); }));

View File

@ -10,40 +10,7 @@ import LinkIcon from '@material-ui/icons/ExitToApp';
import { getServiceUrl } from '../util/config'; import { getServiceUrl } from '../util/config';
const QUERY = ` const QUERY = `
fragment ValueParts on Value { query {
... 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%" ]) { getRecordsByIds(ids: [ "%ID%" ]) {
id id
names names
@ -52,12 +19,12 @@ const QUERY = `
expiryTime expiryTime
owners owners
attributes { attributes {
...AttrParts key
value { value {
... on MapValue { string
map: value { json
...AttrParts 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', flexDirection: 'row',
flex: 1, flex: 1,
justifyContent: 'space-between', justifyContent: 'space-between',
backgroundColor: theme.palette.background.default, backgroundColor: grey[900],
borderTop: 1,
borderTopColor: "rgba(255, 255, 255, 0.12)",
borderTopStyle: "solid",
color: grey[400] color: grey[400]
}, },
left: { left: {

View File

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

View File

@ -37,7 +37,7 @@ const useStyles = makeStyles(theme => ({
const types = [ const types = [
{ key: 'authority', label: 'Authority' }, { key: 'authority', label: 'Authority' },
{ key: 'lrn', label: 'LRN' } { key: 'crn', label: 'CRN' }
]; ];
export const LookupType = ({ scope = types[0].key, onChange }) => { export const LookupType = ({ scope = types[0].key, onChange }) => {
@ -87,7 +87,7 @@ const RegistryLookup = ({ scope }) => {
const getNames = () => { const getNames = () => {
let ret; let ret;
switch (scope) { switch (scope) {
case 'lrn': { case 'crn': {
ret = []; ret = [];
records.forEach(item => ret.push(...(item.names || []))); records.forEach(item => ret.push(...(item.names || [])));
break; break;
@ -99,8 +99,8 @@ const RegistryLookup = ({ scope }) => {
const names = new Set(); const names = new Set();
for (const record of records) { for (const record of records) {
for (const name of (record.names || [])) { for (const name of (record.names || [])) {
// TODO(telackey): We need a general purpose LRN handling library. // TODO(telackey): We need a general purpose CRN handling library.
names.add(name.replace('lrn://', '').split('/')[0]); names.add(name.replace('crn://', '').split('/')[0]);
} }
} }
ret = Array.from(names.values()); ret = Array.from(names.values());
@ -120,7 +120,7 @@ const RegistryLookup = ({ scope }) => {
let result; let result;
switch (scope) { switch (scope) {
case 'lrn': case 'crn':
result = await registry.lookupNames([newInputValue], true); result = await registry.lookupNames([newInputValue], true);
break; 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 // Copyright 2020 DXOS.org
// //
import { Registry } from '@cerc-io/registry-sdk'; import { Registry } from '@cerc-io/laconic-sdk';
import { getServiceUrl } from '../util/config'; 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 debug from 'debug';
import { Registry } from '@cerc-io/registry-sdk'; import { Registry } from '@cerc-io/laconic-sdk';
import { getServiceUrl } from './util/config'; import { getServiceUrl } from './util/config';
@ -45,9 +45,7 @@ export const createResolvers = config => {
wns_records: async (_, { attributes }) => { wns_records: async (_, { attributes }) => {
log('WNS records...'); 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 { return {
__typename: 'JSONResult', __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