forked from cerc-io/laconic-console
Compare commits
65 Commits
zramsay-pa
...
main
Author | SHA1 | Date | |
---|---|---|---|
1e1149eb78 | |||
139fb37bef | |||
4c22335313 | |||
5a09cdd79a | |||
fc83856e11 | |||
c1e368b3b0 | |||
db449e9fe2 | |||
|
b1f95b488c | ||
|
fc76478b8a | ||
4afadb9502 | |||
|
bff6749a91 | ||
a4c15a4d3f | |||
3ead0ee0d0 | |||
aa794637d1 | |||
|
956c84c17e | ||
ccb31956a8 | |||
01122eb7a8 | |||
740143ce7d | |||
4150076469 | |||
7330d03c3c | |||
06726b019d | |||
61f445abe5 | |||
ef73da7ec5 | |||
b9fd355a0e | |||
39ec9a2e31 | |||
6f77228f73 | |||
475f53cdcf | |||
9dcbc6e657 | |||
3458f454a6 | |||
83fca9efe9 | |||
b05706986b | |||
3fe735cb9f | |||
4d3f7d0598 | |||
59ec22ea34 | |||
e1b05a4c34 | |||
41d2278463 | |||
97a100d52f | |||
a1bd672182 | |||
402599662b | |||
c662128f7a | |||
|
0266e7614e | ||
|
052bf92486 | ||
|
8d7b41abcb | ||
f8c8ac1ba6 | |||
1f597fb21a | |||
b82e553001 | |||
5df8740c55 | |||
9dd46987e9 | |||
62ac7d66e2 | |||
|
b8ab4368af | ||
|
9282e9ea26 | ||
|
f1009e6daa | ||
64768e1dc5 | |||
|
072bb718e3 | ||
|
4c8f2a1a26 | ||
|
ce7209453f | ||
|
1aca4e062f | ||
|
2e4f0827d1 | ||
|
a7aaf88d88 | ||
3b9af1f222 | |||
|
30d9841e5e | ||
|
20033ef102 | ||
|
1fd9351a56 | ||
|
8ea5a49d50 | ||
|
8322154f77 |
36
.gitea/workflows/publish-webapp.yaml
Normal file
36
.gitea/workflows/publish-webapp.yaml
Normal 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
|
39
.gitea/workflows/publish.yaml
Normal file
39
.gitea/workflows/publish.yaml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
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
5
.idea/codeStyles/codeStyleConfig.xml
generated
@ -1,5 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<state>
|
|
||||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
|
||||||
</state>
|
|
||||||
</component>
|
|
12
.idea/console.iml
generated
12
.idea/console.iml
generated
@ -1,12 +0,0 @@
|
|||||||
<?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>
|
|
11
.idea/inspectionProfiles/Project_Default.xml
generated
11
.idea/inspectionProfiles/Project_Default.xml
generated
@ -1,11 +0,0 @@
|
|||||||
<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
6
.idea/jsLibraryMappings.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?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
6
.idea/misc.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?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
8
.idea/modules.xml
generated
@ -1,8 +0,0 @@
|
|||||||
<?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
12
.idea/runConfigurations/client.xml
generated
@ -1,12 +0,0 @@
|
|||||||
<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
12
.idea/runConfigurations/server.xml
generated
@ -1,12 +0,0 @@
|
|||||||
<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
6
.idea/vcs.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
2
.npmrc
2
.npmrc
@ -1,2 +0,0 @@
|
|||||||
@cerc-io:registry=https://git.vdb.to/api/packages/cerc-io/npm/
|
|
||||||
@lirewine:registry=https://git.vdb.to/api/packages/cerc-io/npm/
|
|
38
README.md
38
README.md
@ -1,29 +1,27 @@
|
|||||||
# Console
|
# Console
|
||||||
|
|
||||||
Laconic Kubenet GraphQL server and console application.
|
Laconic console application.
|
||||||
|
|
||||||
User interface for submitting and reading records registered on Laconic.
|
User interface for submitting and reading records registered on Laconic.
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
* Clone the required repos:
|
* Clone the required repos:
|
||||||
* [laconicd](https://github.com/cerc-io/laconicd)
|
* [laconicd](https://git.vdb.to/cerc-io/laconicd)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone git@github.com:cerc-io/laconicd.git
|
git clone git@git.vdb.to:cerc-io/laconicd.git
|
||||||
```
|
```
|
||||||
|
|
||||||
* Run the `laconicd` chain:
|
* Run the `laconicd` chain:
|
||||||
* In [laconicd](https://github.com/cerc-io/laconicd) repo, start the chain
|
* In [laconicd](https://git.vdb.to/cerc-io/laconicd) repo, start the chain
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./init.sh
|
./scripts/init.sh clean
|
||||||
```
|
```
|
||||||
|
|
||||||
* Run the laconic-console app
|
* Run the laconic-console app
|
||||||
* In [laconic-console](https://github.com/cerc-io/laconic-console) repo, install dependencies
|
* From the root of this repo, run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn
|
yarn
|
||||||
@ -40,27 +38,23 @@ 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
|
||||||
|
|
||||||
* Change directory to [packages/console-app](https://github.com/cerc-io/laconic-console/tree/main/packages/console-app) and start the react app
|
* Start the 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-app at <http://localhost:8080>
|
* Open console at <http://localhost:8080>
|
||||||
|
|
||||||
* To view records in the app, test suite in laconic-sdk can be run
|
* To view records in the console, the test suite in registry-sdk can be run
|
||||||
|
|
||||||
* Clone the [laconic-sdk](https://github.com/cerc-io/laconic-sdk) repo:
|
* Clone the [registry-sdk](https://git.vdb.to/cerc-io/registry-sdk) repo:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone git@github.com:cerc-io/laconic-sdk.git
|
git clone git@git.vdb.to:cerc-io/registry-sdk.git
|
||||||
```
|
```
|
||||||
|
|
||||||
* 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
|
* 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
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
@ -69,7 +63,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 mykey --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.
|
* Copy the private key exported above and assign it to variable `PRIVATE_KEY` in the `.env` file.
|
||||||
@ -80,12 +74,12 @@ User interface for submitting and reading records registered on Laconic.
|
|||||||
yarn
|
yarn
|
||||||
```
|
```
|
||||||
|
|
||||||
* Run the tests in laconic-sdk repo:
|
* Run the tests in registry-sdk repo:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn test
|
yarn test
|
||||||
```
|
```
|
||||||
|
|
||||||
*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)
|
*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)
|
||||||
|
|
||||||
* Open console-app at <http://localhost:8080> to view the records.
|
* Open console at <http://localhost:8080> to view the records.
|
||||||
|
@ -12,7 +12,6 @@ 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'
|
|
||||||
]
|
]
|
||||||
};
|
};
|
7
build-webapp.sh
Executable file
7
build-webapp.sh
Executable 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"
|
42
config-hosted.yml
Normal file
42
config-hosted.yml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#
|
||||||
|
# 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
|
@ -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'
|
Binary file not shown.
Before Width: | Height: | Size: 820 KiB |
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "1.2.9",
|
|
||||||
"useWorkspaces": true,
|
|
||||||
"npmClient": "yarn"
|
|
||||||
}
|
|
126
package.json
126
package.json
@ -1,69 +1,91 @@
|
|||||||
{
|
{
|
||||||
"name": "laconic-console",
|
"name": "@cerc-io/console-app",
|
||||||
"version": "1.2.9-alpha.0",
|
"version": "0.2.5",
|
||||||
"description": "Laconic Console",
|
"description": "Laconic Console",
|
||||||
"main": "index.js",
|
"repository": "https://github.com/cerc-io/laconic-console",
|
||||||
"private": true,
|
"main": "dist/es/index.js",
|
||||||
|
"files": [
|
||||||
|
"dist/*", "src/*"
|
||||||
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "lerna run build",
|
"analyzer": "webpack --config webpack-analyzer.config.js",
|
||||||
"clean": "lerna run clean",
|
"build": "yarn dist",
|
||||||
"lint": "lerna run lint",
|
"build:babel": "babel ./src --out-dir ./dist/es --ignore \"**/*.test.js\" --source-maps inline",
|
||||||
"lint:fix": "lerna run lint -- --fix",
|
"clean": "rm -rf dist",
|
||||||
"lint:staged": "lint-staged",
|
"updatever": "scripts/update_version.sh > src/version.json",
|
||||||
"sort-package-json": "lerna exec npx sort-package-json",
|
"dist": "yarn clean && yarn updatever && yarn build:babel && CONFIG_FILE=${LACONIC_HOSTED_CONFIG_FILE:-config-production.yml} webpack",
|
||||||
"test": "lerna run test"
|
"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"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "AGPLv3",
|
"license": "GPL-3.0",
|
||||||
"workspaces": {
|
|
||||||
"packages": [
|
|
||||||
"packages/*"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"> 5%"
|
"> 2%"
|
||||||
],
|
],
|
||||||
"jest": {
|
"jest": {
|
||||||
"testEnvironment": "node"
|
"testEnvironment": "node"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lerna": "^3.19.0"
|
"@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"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-eslint": "^10.0.3",
|
"@babel/cli": "7.21.0",
|
||||||
"eslint": "^6.7.2",
|
"@babel/core": "^7.21.0",
|
||||||
"eslint-config-semistandard": "^15.0.0",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"eslint-config-standard": "^14.1.1",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"eslint-loader": "^3.0.3",
|
"@webpack-cli/info": "^2.0.1",
|
||||||
"eslint-plugin-babel": "^5.3.0",
|
"babel-jest": "^29.5.0",
|
||||||
"eslint-plugin-import": "^2.18.2",
|
"babel-loader": "^9.1.2",
|
||||||
"eslint-plugin-jest": "^23.13.1",
|
"babel-plugin-import-graphql": "^2.7.0",
|
||||||
"eslint-plugin-jsdoc": "^21.0.0",
|
"babel-plugin-inline-import": "^3.0.0",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"babel-plugin-inline-json-import": "^0.3.2",
|
||||||
"eslint-plugin-standard": "^4.0.1",
|
"dotenv-webpack": "^8.0.1",
|
||||||
"lint-staged": "^9.5.0",
|
"graphql": "^15.0.0",
|
||||||
"pre-commit": "^1.2.2",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"webpack-cli": "^3.3.11"
|
"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"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"peerDependencies": {
|
||||||
"parser": "babel-eslint",
|
"react": "16.12.0",
|
||||||
"extends": [
|
"react-dom": "^16.12.0"
|
||||||
"plugin:jest/recommended",
|
|
||||||
"semistandard"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"babel"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"babel/semi": 1
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"semistandard": {
|
"publishConfig": {
|
||||||
"parser": "babel-eslint",
|
"access": "public"
|
||||||
"env": [
|
|
||||||
"jest",
|
|
||||||
"node",
|
|
||||||
"browser"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
# 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);
|
|
||||||
```
|
|
@ -1,133 +0,0 @@
|
|||||||
{
|
|
||||||
"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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title><%= title %></title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="root"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,84 +0,0 @@
|
|||||||
//
|
|
||||||
// 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>
|
|
||||||
|
|
||||||
<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;
|
|
@ -1,26 +0,0 @@
|
|||||||
//
|
|
||||||
// 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;
|
|
@ -1,100 +0,0 @@
|
|||||||
//
|
|
||||||
// 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;
|
|
@ -1,32 +0,0 @@
|
|||||||
//
|
|
||||||
// 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;
|
|
@ -1,149 +0,0 @@
|
|||||||
//
|
|
||||||
// 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;
|
|
@ -1,37 +0,0 @@
|
|||||||
//
|
|
||||||
// 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;
|
|
@ -1,79 +0,0 @@
|
|||||||
//
|
|
||||||
// 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'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"build": {
|
|
||||||
"name": "@cerc-io/console-app",
|
|
||||||
"buildDate": "2020-12-19T03:06:08.492Z",
|
|
||||||
"version": "1.2.9-alpha.1"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"build": {
|
|
||||||
"name": "<%= package.name %>",
|
|
||||||
"buildDate": "<%= currentTime.toISOString() %>",
|
|
||||||
"version": "<%= package.version %>"
|
|
||||||
}
|
|
||||||
}
|
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
18
public/index.html
Normal file
18
public/index.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<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>
|
@ -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
69
scripts/publish-app-record.sh
Executable 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
|
61
scripts/request-app-deployment.sh
Executable file
61
scripts/request-app-deployment.sh
Executable 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
|
8
scripts/update_version.sh
Executable file
8
scripts/update_version.sh
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
NAME=`cat package.json | jq '.name'`
|
||||||
|
VERSION=`cat package.json | jq '.version'`
|
||||||
|
DATE=`date --rfc-3339=seconds`
|
||||||
|
|
||||||
|
echo '{"build": {}}' | jq ".build.name = $NAME" | jq ".build.version = $VERSION" | jq ".build.buildDate = \"$DATE\""
|
@ -2,10 +2,7 @@
|
|||||||
// Copyright 2020 DXOS.org
|
// Copyright 2020 DXOS.org
|
||||||
//
|
//
|
||||||
|
|
||||||
import { ApolloClient } from 'apollo-client';
|
import { ApolloClient, InMemoryCache, ApolloLink, HttpLink } 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';
|
||||||
@ -28,7 +25,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 = createHttpLink({
|
const defaultLink = new HttpLink({
|
||||||
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).
|
||||||
@ -39,7 +36,7 @@ export const clientFactory = config => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const serviceLinks = {
|
const serviceLinks = {
|
||||||
signal: createHttpLink({
|
signal: new HttpLink({
|
||||||
uri: getServiceUrl(config, 'signal.api')
|
uri: getServiceUrl(config, 'signal.api')
|
||||||
})
|
})
|
||||||
};
|
};
|
94
src/components/AppBar.js
Normal file
94
src/components/AppBar.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 DXOS.org
|
||||||
|
//
|
||||||
|
|
||||||
|
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/Logo";
|
||||||
|
// 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: "#FBFBFB",
|
||||||
|
},
|
||||||
|
|
||||||
|
link: {
|
||||||
|
color: blueGrey[900],
|
||||||
|
},
|
||||||
|
|
||||||
|
divider: {
|
||||||
|
backgroundColor: theme.palette.text.primary,
|
||||||
|
width: "1px",
|
||||||
|
height: "20px",
|
||||||
|
alignSelf: "center",
|
||||||
|
marginRight: 14,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const AppBar = ({ config }) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<MuiAppBar position="fixed" elevation={0} color="primary">
|
||||||
|
<Toolbar>
|
||||||
|
<Link classes={{ root: classes.logoLink }} href="/">
|
||||||
|
<div className={classes.logo}>
|
||||||
|
<LaconicIcon />
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
<Divider
|
||||||
|
orientation="vertical"
|
||||||
|
flexItem
|
||||||
|
className={classes.divider}
|
||||||
|
/>
|
||||||
|
<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;
|
@ -31,9 +31,9 @@ const getAppUrl = (config, { wrn }) => {
|
|||||||
* @param {string} name
|
* @param {string} name
|
||||||
* @param {string} [text]
|
* @param {string} [text]
|
||||||
*/
|
*/
|
||||||
const AppLink = ({ config, crn, text }) => {
|
const AppLink = ({ config, lrn, text }) => {
|
||||||
const fullURL = getAppUrl(config, { crn });
|
const fullURL = getAppUrl(config, { lrn });
|
||||||
return <Link href={fullURL} target={crn}>{text || crn}</Link>;
|
return <Link href={fullURL} target={lrn}>{text || lrn}</Link>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AppLink;
|
export default AppLink;
|
38
src/components/Json.js
Normal file
38
src/components/Json.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// 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 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")}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Json;
|
@ -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(() => ({
|
const useStyles = makeStyles(theme => ({
|
||||||
root: {
|
root: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
@ -17,7 +17,8 @@ const useStyles = makeStyles(() => ({
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
overflow: 'hidden'
|
overflow: 'hidden',
|
||||||
|
backgroundColor: theme.palette.background.paper,
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
@ -10,7 +10,40 @@ import LinkIcon from '@material-ui/icons/ExitToApp';
|
|||||||
import { getServiceUrl } from '../util/config';
|
import { getServiceUrl } from '../util/config';
|
||||||
|
|
||||||
const QUERY = `
|
const QUERY = `
|
||||||
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%"]) {
|
getRecordsByIds(ids: ["%ID%"]) {
|
||||||
id
|
id
|
||||||
names
|
names
|
||||||
@ -19,12 +52,12 @@ const QUERY = `
|
|||||||
expiryTime
|
expiryTime
|
||||||
owners
|
owners
|
||||||
attributes {
|
attributes {
|
||||||
key
|
...AttrParts
|
||||||
value {
|
value {
|
||||||
string
|
... on MapValue {
|
||||||
json
|
map: value {
|
||||||
reference {
|
...AttrParts
|
||||||
id
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
138
src/components/Sidebar.js
Normal file
138
src/components/Sidebar.js
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
//
|
||||||
|
// 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,
|
||||||
|
},
|
||||||
|
|
||||||
|
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],
|
||||||
|
},
|
||||||
|
|
||||||
|
selected: {
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
},
|
||||||
|
|
||||||
|
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)}
|
||||||
|
classes={{ root: classes.listItem, selected: classes.selected }}
|
||||||
|
>
|
||||||
|
<ListItemIcon classes={{ root: classes.icon }}>
|
||||||
|
<Icon
|
||||||
|
className={clsx(
|
||||||
|
classes.icon,
|
||||||
|
isSelected(path) && classes.selected,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText
|
||||||
|
primary={title.toUpperCase()}
|
||||||
|
classes={{ primary: classes.itemText }}
|
||||||
|
/>
|
||||||
|
</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.toUpperCase()}
|
||||||
|
classes={{ primary: classes.itemText }}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</List>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.root}>
|
||||||
|
<Modules modules={services} />
|
||||||
|
<Extensions extensions={extensions} />
|
||||||
|
<div className={classes.expand} />
|
||||||
|
<Modules modules={settings} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Sidebar;
|
33
src/components/Toolbar.js
Normal file
33
src/components/Toolbar.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// 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),
|
||||||
|
},
|
||||||
|
color: "primary",
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
// TODO(burdon): Tabs.
|
||||||
|
const Toolbar = ({ children }) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MuiToolbar disableGutters className={classes.toolbar}>
|
||||||
|
{children}
|
||||||
|
</MuiToolbar>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Toolbar;
|
@ -28,7 +28,10 @@ const useStyles = makeStyles((theme) => ({
|
|||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'space-between',
|
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]
|
color: grey[400]
|
||||||
},
|
},
|
||||||
left: {
|
left: {
|
@ -2,43 +2,48 @@
|
|||||||
// 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 = () => {
|
||||||
@ -51,10 +56,14 @@ const Registry = () => {
|
|||||||
<Panel
|
<Panel
|
||||||
toolbar={
|
toolbar={
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Tabs value={tab} onChange={(_, value) => setTab(value)}>
|
<Tabs
|
||||||
<Tab value={TAB_RECORDS} label='Records' />
|
value={tab}
|
||||||
<Tab value={TAB_LOOKUP} label='Lookup' />
|
onChange={(_, value) => setTab(value)}
|
||||||
<Tab value={TAB_STATUS} label='Status' />
|
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' /> */}
|
{/* <Tab value={TAB_LOG} label='Log' /> */}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
@ -37,7 +37,7 @@ const useStyles = makeStyles(theme => ({
|
|||||||
|
|
||||||
const types = [
|
const types = [
|
||||||
{ key: 'authority', label: 'Authority' },
|
{ key: 'authority', label: 'Authority' },
|
||||||
{ key: 'crn', label: 'CRN' }
|
{ key: 'lrn', label: 'LRN' }
|
||||||
];
|
];
|
||||||
|
|
||||||
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 'crn': {
|
case 'lrn': {
|
||||||
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 CRN handling library.
|
// TODO(telackey): We need a general purpose LRN handling library.
|
||||||
names.add(name.replace('crn://', '').split('/')[0]);
|
names.add(name.replace('lrn://', '').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 'crn':
|
case 'lrn':
|
||||||
result = await registry.lookupNames([newInputValue], true);
|
result = await registry.lookupNames([newInputValue], true);
|
||||||
break;
|
break;
|
||||||
|
|
186
src/containers/panels/registry/RegistryRecords.js
Normal file
186
src/containers/panels/registry/RegistryRecords.js
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 DXOS.org
|
||||||
|
//
|
||||||
|
|
||||||
|
import moment from 'moment';
|
||||||
|
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';
|
||||||
|
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';
|
||||||
|
|
||||||
|
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: 'lrn:kube', label: 'Kube' },
|
||||||
|
{ key: 'lrn:service', label: 'Service' },
|
||||||
|
{ key: 'lrn:app', label: 'App' },
|
||||||
|
{ key: 'lrn:bot', label: 'Bot' },
|
||||||
|
{ key: 'lrn:bot-factory', label: 'Bot Factory' },
|
||||||
|
{ key: 'lrn:file', label: 'File' },
|
||||||
|
{ key: 'lrn: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 [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, limit: rowsPerPage, offset: offset } }
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<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;
|
||||||
|
|
||||||
|
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>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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>
|
||||||
|
</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>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RegistryRecords;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user