Skip to content

Commit

Permalink
Support multiple stacks per network in Dashboard (#3162)
Browse files Browse the repository at this point in the history
* feat: Support array of stacks in build env

* fix: change dist path to public in build env script

* feat:
- add Monitor elements in html
- define services classes and showMonitorErrors
- implement showMonitorErrors that change loader dom to show monitor results


* chore: support defineAsyncComponent and use it for some components
add setGlobalEnv that check all services stacks and set the available url in env

* Docs: add stacks support docs
  • Loading branch information
0oM4R authored Aug 18, 2024
1 parent 799ac82 commit 28e17de
Show file tree
Hide file tree
Showing 13 changed files with 242 additions and 51 deletions.
2 changes: 2 additions & 0 deletions packages/playground/docs/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ bash ../scripts/build-env.sh
- SENTRY_DSN
- ENABLE_TELEMETRY
- The use can provide a single URL or multiple URLs separated with a comma, for `GRAPHQL_URL, GRIDPROXY_URL, SUBSTRATE_URL, ACTIVATION_SERVICE_URL, RELAY_DOMAIN, STATS_URL`, If the user provides multiple URLs, it will be considered as a priority list, which means the dashboard will try to connect over the first URL in the list; if it fails, it will move to the next one, and so on.
- The backend payments are done with stellar so you need to decide which network of stellar you want to connect to
```bash
Expand Down
7 changes: 6 additions & 1 deletion packages/playground/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@
});
</script>
<img class="logo_load" src="/images/logo_text.png" alt="logo" />
<span class="app-loader-msg">Loading dashboard. Please wait...</span>
<span class="app-loader-msg active">Loading dashboard. Please wait...</span>
<span class="app-monitor-msg"></span>
<div class="app-monitor-container">
<ul class="app-monitor-status">
</ul>
</div>
<button class="app-loader-refresh">Refresh</button>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions packages/playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@threefold/graphql_client": "2.5.0",
"@threefold/grid_client": "2.5.0",
"@threefold/gridproxy_client": "2.5.0",
"@threefold/monitoring": "2.5.0",
"@threefold/types": "2.5.0",
"@types/ip": "^1.1.3",
"@types/md5": "^2.3.5",
Expand Down
15 changes: 9 additions & 6 deletions packages/playground/public/config.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
window.env = {
NETWORK: "dev",
GRAPHQL_URL: "https://graphql.dev.grid.tf/graphql",
GRIDPROXY_URL: "https://gridproxy.dev.grid.tf",
SUBSTRATE_URL: "wss://tfchain.dev.grid.tf/ws",
ACTIVATION_SERVICE_URL: "https://activation.dev.grid.tf/activation/activate",
RELAY_DOMAIN: "wss://relay.dev.grid.tf",
GRAPHQL_STACKS: ["https://graphql.dev.grid.tf/graphql", "https://graphql.02.dev.grid.tf/graphql"],
GRIDPROXY_STACKS: ["https://gridproxy.dev.grid.tf", "https://gridproxy.02.dev.grid.tf"],
SUBSTRATE_STACKS: ["wss://tfchain.dev.grid.tf/ws", "wss://tfchain.02.dev.grid.tf/ws"],
ACTIVATION_SERVICE_STACKS: [
"https://activation.dev.grid.tf/activation/activate",
"https://activation.02.dev.grid.tf/activation/activate",
],
RELAY_STACKS: ["wss://relay.dev.grid.tf", "wss://relay.02.dev.grid.tf"],
BRIDGE_TFT_ADDRESS: "GDHJP6TF3UXYXTNEZ2P36J5FH7W4BJJQ4AYYAXC66I2Q2AH5B6O6BCFG",
STELLAR_NETWORK: "test",
STELLAR_HORIZON_URL: "https://horizon-testnet.stellar.org",
TFT_ASSET_ISSUER: "GA47YZA3PKFUZMPLQ3B5F2E3CJIB57TGGU7SPCQT2WAEYKN766PWIMB3",
MINTING_URL: "https://alpha.minting.tfchain.grid.tf",
STATS_URL: "https://stats.dev.grid.tf",
STATS_STACKS: ["https://stats.dev.grid.tf", "https://stats.02.dev.grid.tf"],
TIMEOUT: +"10000",
PAGE_SIZE: +"20",
MANUAL_URL: "https://www.manual.grid.tf",
Expand Down
62 changes: 60 additions & 2 deletions packages/playground/public/loader/loader.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,54 @@
margin-top: 30vh;
}

.app-monitor-container {
flex-direction: column;
align-items: center;
margin-top: 20px;
display: none;
border: 1px solid #fff;
border-radius: 5px;
padding: 5px 25px;
}

.app-monitor-container.active {
display: flex;
}

.app-monitor-status {
text-align: left;
color: #fff;
margin: 0;
font-family: sans-serif;
max-width: 500px;
line-height: 1;
}

.service-name {
color: #fff;
width: 100px;
padding: 2px 0;
font-family: sans-serif;
line-height: 1;
font-weight: bold;
text-align: left;
}

.service-status {
display: inline;
font-family: sans-serif;
line-height: 1;
font-weight: bold;
font-size: x-large;
}

.service-reachable {
color: rgb(var(--v-theme-success, "76, 175, 80"));
}

.service-unreachable {
color: rgb(207 102 121);
}
.app-loader-logo {
max-width: 100%;
display: block;
Expand Down Expand Up @@ -86,7 +134,9 @@
}
}

.app-loader-msg {
.app-loader-msg,
.app-monitor-msg {
display: none;
color: #fff;
margin: 0;
margin-top: 20px;
Expand All @@ -96,6 +146,14 @@
text-align: center;
}

.app-monitor-msg {
display: none;
}

.app-loader-msg.active,
.app-monitor-msg.active {
display: block;
}
.app-loader-refresh {
border: none;
outline: none;
Expand Down Expand Up @@ -134,4 +192,4 @@

.app-loader-refresh:focus {
box-shadow: 0 0 0 2px rgba(115, 221, 195, 0.5);
}
}
28 changes: 28 additions & 0 deletions packages/playground/public/loader/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ const msgElement = document.querySelector(".app-loader-msg");
/** @type { HTMLButtonElement} */
const refreshBtn = document.querySelector(".app-loader-refresh");

/** @type { HTMLDivElement } */
const monitor = document.querySelector(".app-monitor-container");

/** @type { HTMLUListElement} */
const monitorList = document.querySelector(".app-monitor-status");

const slowConnectionTime = 60 * 1000;
const noConnectionTime = 120 * 1000;
const appLoaderContainerTime = 0.3 * 1000;
Expand Down Expand Up @@ -58,3 +64,25 @@ window.$$appLoader = () => {
}
}, welcomeMsgTime);
};
window.$$showMonitorError = urls => {
if (msgElement) msgElement.classList.remove("active");

if (monitor) monitor.classList.add("active");

const monitorMsgElement = document.querySelector(".app-monitor-msg");
if (monitorMsgElement) {
monitorMsgElement.classList.add("active");
monitorMsgElement.textContent = "Can't reach some services on provided stacks, Please try again";
}

if (monitorList) {
monitorList.innerHTML = Object.entries(urls).map(createElement).join(" ");
}
refreshBtn && refreshBtn.classList.add("active");
};

function createElement([serviceName, serviceStatus]) {
return `<li><div style="display:flex"><p class="service-name">${serviceName}</p> <p class="service-status service-${
serviceStatus !== null ? "reachable" : "unreachable"
}">${serviceStatus !== null ? "&#10003;" : "&#10007;"}</p></div></li>`;
}
77 changes: 46 additions & 31 deletions packages/playground/scripts/build-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,46 +15,46 @@ STELLAR_ENV_Vars=(

case $MODE in
"dev")
GRAPHQL_URL="${GRAPHQL_URL:-https://graphql.dev.grid.tf/graphql}"
GRIDPROXY_URL="${GRIDPROXY_URL:-https://gridproxy.dev.grid.tf}"
SUBSTRATE_URL="${SUBSTRATE_URL:-wss://tfchain.dev.grid.tf/ws}"
ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-https://activation.dev.grid.tf/activation/activate}"
RELAY_DOMAIN="${RELAY_DOMAIN:-wss://relay.dev.grid.tf}"
GRAPHQL_URL="${GRAPHQL_URL:-"https://graphql.dev.grid.tf/graphql,https://graphql.02.dev.grid.tf/graphql"}"
GRIDPROXY_URL="${GRIDPROXY_URL:-"https://gridproxy.dev.grid.tf,https://gridproxy.02.dev.grid.tf"}"
SUBSTRATE_URL="${SUBSTRATE_URL:-"wss://tfchain.dev.grid.tf/ws,wss://tfchain.02.dev.grid.tf/ws"}"
ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-"https://activation.dev.grid.tf/activation/activate,https://activation.02.dev.grid.tf/activation/activate"}"
RELAY_DOMAIN="${RELAY_DOMAIN:-"wss://relay.dev.grid.tf,wss://relay.02.dev.grid.tf"}"
BRIDGE_TFT_ADDRESS="${BRIDGE_TFT_ADDRESS:-GDHJP6TF3UXYXTNEZ2P36J5FH7W4BJJQ4AYYAXC66I2Q2AH5B6O6BCFG}"
STATS_URL="${STATS_URL:-https://stats.dev.grid.tf}"
STATS_URL="${STATS_URL:-"https://stats.dev.grid.tf,https://stats.02.dev.grid.tf"}"
STELLAR_NETWORK="${STELLAR_NETWORK:-test}"
SENTRY_DSN="https://[email protected]/2"
;;
"qa")
GRAPHQL_URL="${GRAPHQL_URL:-https://graphql.qa.grid.tf/graphql}"
GRIDPROXY_URL="${GRIDPROXY_URL:-https://gridproxy.qa.grid.tf}"
SUBSTRATE_URL="${SUBSTRATE_URL:-wss://tfchain.qa.grid.tf/ws}"
ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-https://activation.qa.grid.tf/activation/activate}"
RELAY_DOMAIN="${RELAY_DOMAIN:-wss://relay.qa.grid.tf}"
GRAPHQL_URL="${GRAPHQL_URL:-"https://graphql.qa.grid.tf/graphql,https://graphql.02.qa.grid.tf/graphql"}"
GRIDPROXY_URL="${GRIDPROXY_URL:-"https://gridproxy.qa.grid.tf,https://gridproxy.02.qa.grid.tf"}"
SUBSTRATE_URL="${SUBSTRATE_URL:-"wss://tfchain.qa.grid.tf/ws,wss://tfchain.02.qa.grid.tf/ws"}"
ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-"https://activation.qa.grid.tf/activation/activate,https://activation.02.qa.grid.tf/activation/activate"}"
RELAY_DOMAIN="${RELAY_DOMAIN:-"wss://relay.qa.grid.tf,wss://relay.02.qa.grid.tf"}"
BRIDGE_TFT_ADDRESS="${BRIDGE_TFT_ADDRESS:-GAQH7XXFBRWXT2SBK6AHPOLXDCLXVFAKFSOJIRMRNCDINWKHGI6UYVKM}"
STATS_URL="${STATS_URL:-https://stats.qa.grid.tf}"
STATS_URL="${STATS_URL:-"https://stats.qa.grid.tf,https://stats.02.qa.grid.tf"}"
STELLAR_NETWORK="${STELLAR_NETWORK:-test}"
SENTRY_DSN="https://[email protected]/2"
;;
"test")
GRAPHQL_URL="${GRAPHQL_URL:-https://graphql.test.grid.tf/graphql}"
GRIDPROXY_URL="${GRIDPROXY_URL:-https://gridproxy.test.grid.tf}"
SUBSTRATE_URL="${SUBSTRATE_URL:-wss://tfchain.test.grid.tf/ws}"
ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-https://activation.test.grid.tf/activation/activate}"
RELAY_DOMAIN="${RELAY_DOMAIN:-wss://relay.test.grid.tf}"
GRAPHQL_URL="${GRAPHQL_URL:-"https://graphql.test.grid.tf/graphql,https://graphql.02.test.grid.tf/graphql"}"
GRIDPROXY_URL="${GRIDPROXY_URL:-"https://gridproxy.test.grid.tf,https://gridproxy.02.test.grid.tf"}"
SUBSTRATE_URL="${SUBSTRATE_URL:-"wss://tfchain.test.grid.tf/ws,wss://tfchain.02.test.grid.tf/ws"}"
ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-"https://activation.test.grid.tf/activation/activate,https://activation.02.test.grid.tf/activation/activate"}"
RELAY_DOMAIN="${RELAY_DOMAIN:-"wss://relay.test.grid.tf,wss://relay.02.test.grid.tf"}"
BRIDGE_TFT_ADDRESS="${BRIDGE_TFT_ADDRESS:-GA2CWNBUHX7NZ3B5GR4I23FMU7VY5RPA77IUJTIXTTTGKYSKDSV6LUA4}"
STATS_URL="${STATS_URL:-https://stats.test.grid.tf}"
STATS_URL="${STATS_URL:-"https://stats.test.grid.tf,https://stats.02.test.grid.tf"}"
STELLAR_NETWORK="${STELLAR_NETWORK:-main}"
SENTRY_DSN="https://[email protected]/2"
;;
"main")
GRAPHQL_URL="${GRAPHQL_URL:-https://graphql.grid.tf/graphql}"
GRIDPROXY_URL="${GRIDPROXY_URL:-https://gridproxy.grid.tf}"
SUBSTRATE_URL="${SUBSTRATE_URL:-wss://tfchain.grid.tf/ws}"
ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-https://activation.grid.tf/activation/activate}"
RELAY_DOMAIN="${RELAY_DOMAIN:-wss://relay.grid.tf}"
GRAPHQL_URL="${GRAPHQL_URL:-"https://graphql.grid.tf/graphql,https://graphql.02.grid.tf/graphql"}"
GRIDPROXY_URL="${GRIDPROXY_URL:-"https://gridproxy.grid.tf,https://gridproxy.02.grid.tf"}"
SUBSTRATE_URL="${SUBSTRATE_URL:-"wss://tfchain.grid.tf/ws,wss://tfchain.02.grid.tf/ws"}"
ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-"https://activation.grid.tf/activation/activate,https://activation.02.grid.tf/activation/activate"}"
RELAY_DOMAIN="${RELAY_DOMAIN:-"wss://relay.grid.tf,wss://relay.02.grid.tf"}"
BRIDGE_TFT_ADDRESS="${BRIDGE_TFT_ADDRESS:-GBNOTAYUMXVO5QDYWYO2SOCOYIJ3XFIP65GKOQN7H65ZZSO6BK4SLWSC}"
STATS_URL="${STATS_URL:-https://stats.grid.tf}"
STATS_URL="${STATS_URL:-"https://stats.grid.tf,https://stats.02.grid.tf"}"
STELLAR_NETWORK="${STELLAR_NETWORK:-main}"
SENTRY_DSN="https://[email protected]/2"
;;
Expand All @@ -81,20 +81,35 @@ case $STELLAR_NETWORK in
;;
esac

parss_array(){
local service_urls=$1
toString=($(echo "$service_urls" | tr ',' "\n"))
for item in "${toString[@]}"; do
quoted_string+="'$item' "
done

# add single quate to each elament
quoted_string=${quoted_string// /,}

# remove trailing comma
echo "${quoted_string%?}"

}

configs="
window.env = {
NETWORK: '$MODE',
GRAPHQL_URL: '$GRAPHQL_URL',
GRIDPROXY_URL: '$GRIDPROXY_URL',
SUBSTRATE_URL: '$SUBSTRATE_URL',
ACTIVATION_SERVICE_URL: '$ACTIVATION_SERVICE_URL',
RELAY_DOMAIN: '$RELAY_DOMAIN',
GRAPHQL_STACKS: "[$(parss_array "$GRAPHQL_URL")]",
GRIDPROXY_STACKS: "[$(parss_array "$GRIDPROXY_URL")]",
SUBSTRATE_STACKS: "[$(parss_array "$SUBSTRATE_URL")]",
ACTIVATION_SERVICE_STACKS: "[$(parss_array "$ACTIVATION_SERVICE_URL")]",
RELAY_STACKS: "[$(parss_array "$RELAY_DOMAIN")]",
BRIDGE_TFT_ADDRESS: '$BRIDGE_TFT_ADDRESS',
STELLAR_NETWORK: '$STELLAR_NETWORK',
STELLAR_HORIZON_URL: '$STELLAR_HORIZON_URL',
TFT_ASSET_ISSUER: '$TFT_ASSET_ISSUER',
MINTING_URL: '$MINTING_URL',
STATS_URL: '$STATS_URL',
STATS_STACKS: "[$(parss_array "$STATS_URL")]",
TIMEOUT: +'$TIMEOUT',
PAGE_SIZE: +'$PAGE_SIZE',
MANUAL_URL: '$MANUAL_URL',
Expand All @@ -104,7 +119,7 @@ window.env = {
"

# decide the config file path
[ -d dist ] && file="dist/config.js" || file="config.js"
[ -d public ] && file="public/config.js" || file="config.js"

# override the content of the config file & echo the result
echo $configs > $file
Expand Down
26 changes: 26 additions & 0 deletions packages/playground/src/Monitor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<template>
<template v-if="!loadingApp">
<App />
</template>
</template>

<script lang="ts">
import { defineAsyncComponent, onMounted, ref } from "vue";
import { setGlobalEnv } from "./config";
export default {
name: "AppMonitor",
components: {
App: defineAsyncComponent(() => import("./App.vue")),
},
setup() {
const loadingApp = ref(true);
onMounted(async () => {
if (await setGlobalEnv()) {
loadingApp.value = false;
}
});
return { loadingApp };
},
};
</script>
1 change: 0 additions & 1 deletion packages/playground/src/clients/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import TFGridGqlClient from "@threefold/graphql_client";
import GridProxyClient from "@threefold/gridproxy_client";
import { QueryClient } from "@threefold/tfchain_client";

const gqlClient = new TFGridGqlClient(window.env.GRAPHQL_URL);
const gridProxyClient = new GridProxyClient(window.env.GRIDPROXY_URL);
const queryClient = new QueryClient(window.env.SUBSTRATE_URL);
Expand Down
2 changes: 1 addition & 1 deletion packages/playground/src/components/logger.vue
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export default {
let _interceptorQueue: LI[] = [];
async function interceptMessage(instance: LI) {
if (connectDB.value.error) {
if (connectDB.value.error ) {
_interceptorQueue.push(instance);
return;
}
Expand Down
Loading

0 comments on commit 28e17de

Please sign in to comment.