From 253134e30dbd752dd2fcf42a8ade10eeff355f24 Mon Sep 17 00:00:00 2001 From: Mikhailo Marynenko <0x77dev@protonmail.com> Date: Thu, 27 Jan 2022 22:55:22 +0200 Subject: [PATCH] feat(explorer): add some elements --- packages/explorer/.parcelrc | 7 +++ packages/explorer/README.md | 4 ++ packages/explorer/package.json | 2 + packages/explorer/project.json | 60 +++++++++--------------- packages/explorer/src/app.tsx | 33 ++++++++----- packages/explorer/src/dashboard.tsx | 72 +++++++++++++++++++++++++++++ packages/lib/src/stack.ts | 5 +- yarn.lock | 14 ++++++ 8 files changed, 145 insertions(+), 52 deletions(-) create mode 100644 packages/explorer/src/dashboard.tsx diff --git a/packages/explorer/.parcelrc b/packages/explorer/.parcelrc index e2736c9..7bbed9d 100644 --- a/packages/explorer/.parcelrc +++ b/packages/explorer/.parcelrc @@ -1,4 +1,11 @@ { + "compressors": { + "*.{html,css,js,svg,map}": [ + "...", + "@parcel/compressor-gzip", + "@parcel/compressor-brotli" + ] + }, "extends": "@parcel/config-default", "transformers": { "*.svg": [ diff --git a/packages/explorer/README.md b/packages/explorer/README.md index 049e7a0..f2768c1 100644 --- a/packages/explorer/README.md +++ b/packages/explorer/README.md @@ -3,3 +3,7 @@ Simple playground to play around with DStack [Open](https://dstack-explorer.netlify.app/) + +### P.S. + +I'm not familiar with react, so there may be some dirty code, if you are web developer and want to join DStack text us in [discord](https://discord.gg/vWS9yzjA57). diff --git a/packages/explorer/package.json b/packages/explorer/package.json index c58c117..4a14d49 100644 --- a/packages/explorer/package.json +++ b/packages/explorer/package.json @@ -14,6 +14,8 @@ "description": "DStack Web explorer/playground to debug your project or just play around", "devDependencies": { "@emotion/babel-plugin": "^11.7.2", + "@parcel/compressor-brotli": "^2.2.1", + "@parcel/compressor-gzip": "^2.2.1", "@parcel/config-default": "^2.2.1", "@parcel/transformer-svg-react": "^2.2.1", "@types/react": "^17.0.38", diff --git a/packages/explorer/project.json b/packages/explorer/project.json index b954696..175d7eb 100644 --- a/packages/explorer/project.json +++ b/packages/explorer/project.json @@ -1,49 +1,31 @@ { "projectType": "application", "root": "packages/explorer", + "serve": { + "executor": "@nrwl/workspace:run-commands", + "options": { + "commands": [ + "nx build lib", + "nx build ipfs", + "cd packages/explorer && yarn serve" + ], + "cwd": "/" + } + }, "sourceRoot": "packages/explorer/src", "tags": [], "targets": { - "build": { - "dependsOn": [ - { - "projects": "dependencies", - "target": "ipfs:build" - }, - { - "projects": "dependencies", - "target": "lib:build" - } + "executor": "@nrwl/workspace:run-commands", + "options": { + "commands": [ + "nx build lib", + "nx build ipfs", + "yarn build" ], - "executor": "@nrwl/workspace:run-commands", - "options": { - "commands": [ - "yarn build" - ], - "cwd": "packages/explorer" - }, - "outputs": [ - "packages/explorer/dist" - ] + "cwd": "/" }, - "serve": { - "dependsOn": [ - { - "projects": "dependencies", - "target": "ipfs:build" - }, - { - "projects": "dependencies", - "target": "lib:build" - } - ], - "executor": "@nrwl/workspace:run-commands", - "options": { - "commands": [ - "yarn serve" - ], - "cwd": "packages/explorer" - } - } + "outputs": [ + "packages/explorer/dist" + ] } } diff --git a/packages/explorer/src/app.tsx b/packages/explorer/src/app.tsx index d146c2d..56b0cd9 100644 --- a/packages/explorer/src/app.tsx +++ b/packages/explorer/src/app.tsx @@ -1,28 +1,39 @@ import { create } from '@dstack-js/ipfs'; import { Stack } from '@dstack-js/lib'; import React, { useState } from 'react'; +import { Dashboard } from './dashboard'; export const App: React.FunctionComponent<{}> = () => { - const [ready, setReady] = useState(false); + const [stack, setStack] = useState(null); + const [fillInfo, setFillInfo] = useState(true); + const [namespace, setNamespace] = useState('dstack'); const init = async (): Promise => { + setFillInfo(false); localStorage.setItem('debug', '*'); + const ipfs = await create(); - const stack = await Stack.create('stack', ipfs); + const stack = await Stack.create(namespace, ipfs); stack.debug(); + // @ts-expect-error window.stack = stack; - setReady(true); + setStack(stack); }; - React.useEffect(() => { - init(); - }, []); + if (fillInfo) { + return ( +
+ setNamespace(e.target.value)} + > + +
+ ); + } - return ready ? ( -
use `window.stack` to get started
- ) : ( -

Initializing

- ); + return stack ? :

Initializing

; }; diff --git a/packages/explorer/src/dashboard.tsx b/packages/explorer/src/dashboard.tsx new file mode 100644 index 0000000..3c27f13 --- /dev/null +++ b/packages/explorer/src/dashboard.tsx @@ -0,0 +1,72 @@ +import { Stack, Peer } from '@dstack-js/lib'; +import React, { useEffect, useState } from 'react'; + +export const Dashboard: React.FunctionComponent<{ stack: Stack }> = (props) => { + const [peers, setPeers] = useState([]); + const [topic, setTopic] = useState('date'); + const [events, setEvents] = useState([]); + + useEffect(() => { + props.stack.pubsub.subscribe('$store', (msg) => { + events.push(`$store: ${msg.from} ${(msg.data as any).key}`); + setEvents(events.slice(1).slice(-5)); + }); + + const updateState = async () => { + setPeers(await props.stack.peers()); + }; + + const interval = setInterval(() => { + updateState(); + }, 100); + + return () => { + props.stack.pubsub.unsubscribe('$store'); + clearInterval(interval); + }; + }, []); + + useEffect(() => { + props.stack.pubsub.subscribe(topic, (msg) => { + events.push(`${topic}: ${msg.from} ${msg.data}`); + setEvents(events.slice(1).slice(-5)); + }); + + return () => { + props.stack.pubsub.unsubscribe(topic); + }; + }, [topic]); + + return ( +
+
use `window.stack` to interact with DStack
+
+ Topic: + setTopic(e.target.value)} + /> +
+ +
+

Connected Peers:

+ {peers.map((peer) => ( +
  • {peer.id}
  • + ))} +
    +

    Captured events:

    + {events.map((event) => ( +
    + {event}
    +
    + ))} +
    + ); +}; diff --git a/packages/lib/src/stack.ts b/packages/lib/src/stack.ts index 2377d59..ffc7f7e 100644 --- a/packages/lib/src/stack.ts +++ b/packages/lib/src/stack.ts @@ -12,7 +12,7 @@ export class Stack { public store: Store public pubsub: PubSub - private constructor(public namespace: string, public ipfs: IPFS) { + private constructor(public namespace: string, public ipfs: IPFS, public id: string) { this.pubsub = new PubSub(ipfs, namespace) this.store = new Store(ipfs, namespace, this.pubsub) } @@ -29,7 +29,8 @@ export class Stack { * @returns Stack instance */ public static async create(namespace: string, ipfs: IPFS) { - const stack = new Stack(namespace, ipfs) + const { id } = await ipfs.id() + const stack = new Stack(namespace, ipfs, id) await stack.store.start() return stack diff --git a/yarn.lock b/yarn.lock index 6dc6cf4..cca444e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3901,6 +3901,20 @@ slice-ansi "^4.0.0" string-width "^4.2.0" +"@parcel/compressor-brotli@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@parcel/compressor-brotli/-/compressor-brotli-2.2.1.tgz#0ebcb44f656e0f2093f6fa43ef074fbc12d77a49" + integrity sha512-CXmneKgudev9VthRShKL20JTV8paYS53A2LBA5nspfgEPnbFeAzX2LV0/QqY983+f+WCEWzieySGcVRxCxK5nQ== + dependencies: + "@parcel/plugin" "^2.2.1" + +"@parcel/compressor-gzip@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@parcel/compressor-gzip/-/compressor-gzip-2.2.1.tgz#3c9182888ca83f86e8f1da48bbe2059e50ee7bb1" + integrity sha512-aj9TQifbxqWNQxhUUMvC/UJ6+fY+nPrqJbAJHjrJGrbYncjS0jok1Wkh40iu0qY5OAz3YGUvzadr3nFgL5UsDQ== + dependencies: + "@parcel/plugin" "^2.2.1" + "@parcel/compressor-raw@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@parcel/compressor-raw/-/compressor-raw-2.2.1.tgz#fd2d19d8939cfdee23e95b3e95a3d6b102c3f2f3"