Skip to content
This repository was archived by the owner on Aug 30, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ There is a several component in the weblets repo, you can find them in the `/src
- [Casperlabs](/src/elements/casperlabs)
- [Node Pilot](/src/elements/nodePilot)
- [Full Virtual Machine](/src/elements/fullvm)
- [FreeFlow](/src/elements/freeflow)
- Utils Components
- [Base](/src/elements/base)
- [Profile](/src/elements/profiles)
Expand Down
Binary file added playground/public/icons/freeflow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion playground/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
<script lang="ts">
import { Component, Vue, Watch } from "vue-property-decorator";
import Sidenav from "@/components/Sidenav.vue";
import api from "@/utils/api";
import { ISidenav } from "@/types/Sidenav";
import { Route } from "vue-router";
import { findInitialPage } from "@/utils/sidenav";
Expand Down Expand Up @@ -54,6 +53,7 @@ export default class App extends Vue {
"tfhubvalidator",
"nodepilot",
"fullvm",
'freeflow',
"algorand",
];
sidenav: ISidenav | null = null;
Expand Down
2 changes: 2 additions & 0 deletions playground/src/views/Editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ export default class Editor extends Vue {
),*/
new Weblet("Node Pilot", "nodepilot", "nodepilot", "deployment", "vm.png"),

new Weblet("FreeFlow", "freeflow", "freeflow", "deployment", "freeflow.png"),

new Weblet("Contracts", "contractslist", "", "my account", ""),
new Weblet("Deployments", "deployedlist", "", "my account", ""),

Expand Down
9 changes: 5 additions & 4 deletions src/elements/DeployedList/DeployedList.wc.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
{ label: "Algorand", value: "algorand" },
//{ label: "TFhub Validator", value: "tfhubValidator" },
{ label: "Node Pilot", value: "nodepilot" },
{ label: "FreeFlow", value: "freeflow" },
];
let active: string = "vm";
$: active = tab || active;
Expand Down Expand Up @@ -526,8 +527,8 @@
<Alert
type="warning"
message={`
Failed to load
<strong>${rows.total - rows.data.length}</strong>
Failed to load
<strong>${rows.total - rows.data.length}</strong>
out of ${rows.total} Deployments`}
/>
{/if}
Expand Down Expand Up @@ -583,8 +584,8 @@
<Alert
type="warning"
message={`
Failed to load
<strong>${rows.total - rows.data.length}</strong>
Failed to load
<strong>${rows.total - rows.data.length}</strong>
out of ${rows.total} Deployments`}
/>
{/if}
Expand Down
209 changes: 209 additions & 0 deletions src/elements/freeflow/Freeflow.wc.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
<svelte:options tag="tf-freeflow"/>

<SelectProfile on:profile={({ detail }) => (profile = detail)}/>

<script lang="ts">
import SelectProfile from "../../components/SelectProfile.svelte";
import Input from "../../components/Input.svelte";
import Tabs from "../../components/Tabs.svelte";
import DeployBtn from "../../components/DeployBtn.svelte";
import Alert from "../../components/Alert.svelte";
import type {IFormField, ITab} from "../../types";
import type {IProfile} from "../../types/Profile";
import type {GatewayNodes} from "../../utils/gatewayHelpers";
import FreeFlow from "../../types/freeflow";
import {validateFlistvalue, validateThreeBotName} from "../../utils/validateName";
import {Env} from "../../types/vm";
import SelectGatewayNode from "../../components/SelectGatewayNode.svelte";
import SelectNodeId from "../../components/SelectNodeId.svelte";
import {noActiveProfile} from "../../utils/message";
import Modal from "../../components/DeploymentModal.svelte";
import deployFreeFlow from "../../utils/deployFreeFlow";
import hasEnoughBalance from "../../utils/hasEnoughBalance";

const data = new FreeFlow();

let profile: IProfile;

let loading = false;
let success = false;
let failed = false;

let invalidGateway = true;
let status = "valid" | "invalid";

let gateway: GatewayNodes;
let modalData: Object;

const validateFlist = {
loading: false,
error: null,
validator: validateFlistvalue,
invalid: false,
};

let message: string;

const deploymentStore = window.configs?.deploymentStore;
const currentDeployment = window.configs?.currentDeploymentStore;

const tabs: ITab[] = [
{label: "Config", value: "config"},
];


let active = "config";


// prettier-ignore
const nameField: IFormField =
{
label: "Name",
symbol: "name",
placeholder: "Your 3bot name",
type: "text",
validator: validateThreeBotName,
invalid: false
};


$: disabled = nameField.invalid | invalidGateway | status != 'valid'

const deployFreeFlowHandler = () => {
loading = true;

const gatewayName = (data.threeBotUserId + '.' + gateway.nodeDomain);

data.envs[1] = new Env(undefined, 'USER_ID', data.threeBotUserId)
data.envs[2] = new Env(undefined, 'DIGITALTWIN_APPID', gatewayName)
data.envs[3] = new Env(undefined, 'NODE_ENV', 'staging')

if (!hasEnoughBalance()) {
failed = true;
loading = false;
message =
"No enough balance to execute transaction requires 2 TFT at least in your wallet.";
return;
}

success = false;
failed = false;
message = undefined;

deployFreeFlow(data, profile, "VM")
.then((data) => {
deploymentStore.set(0);
success = true;
modalData = data;
})
.catch((err: Error) => {
failed = true;
message = typeof err === "string" ? err : err.message;
})
.finally(() => {
validateFlist.loading = false;
loading = false;
});
}

$: logs = $currentDeployment;
</script>

<SelectProfile
on:profile={({ detail }) => {
profile = detail;
if (detail) {
data.envs[0] = new Env(undefined, "SSH_KEY", detail?.sshKey);
}
}}
/>


<div style="padding: 15px">
<form class="box" on:submit|preventDefault={deployFreeFlowHandler}>
<h4 class="is-size-4 mb-4">Deploy a FreeFlow Instance</h4>
<p>
Freeflow is a convenient ecosystem on top of a resilient internet grid. We bring you a new internet with a
set of productivity tools so you can enhance collaboration within your country, your company, your community
<!-- @TODO: fix URL-->
<a
target="_blank"
href="https://library.threefold.me/info/manual/#/manual__weblets_freeflow"
>
Quick start documentation</a
>
</p>

<hr/>

{#if loading || (logs !== null && logs.type === "FreeFlow")}
<Alert type="info" message={logs?.message ?? "Loading..."}/>

{:else if !profile}
<Alert type="info" message={noActiveProfile}/>

{:else if success}
<Alert
type="success"
message="Successfully Deployed FreeFlow."
deployed={true}
/>
{:else if failed}
<Alert type="danger" message={message || "Failed to Deploy FreeFlow."}/>
{:else}
<Tabs bind:active {tabs}/>

<Input
bind:data={data.threeBotUserId}
bind:invalid={nameField.invalid}
field={nameField}
/>

<SelectGatewayNode
bind:gateway
bind:invalid={invalidGateway}

/>
<SelectNodeId
publicIp={data.publicIp}
cpu={data.cpu}
memory={data.memory}
ssd={data.disks.reduce(
(total, disk) => total + disk.size,
data.rootFs
)}
bind:nodeSelection={data.selection.type}
bind:data={data.nodeId}
filters={data.selection.filters}
bind:status
{profile}
on:fetch={({ detail }) => (data.selection.nodes = detail)}
nodes={data.selection.nodes}
/>
{/if}

<DeployBtn
disabled={disabled}
{loading}
{success}
{failed}
on:click={(e) => {
if (success || failed) {
e.preventDefault();
success = false;
failed = false;
loading = false;
}
}}
/>
</form>
</div>

{#if modalData}
<Modal data={modalData} on:closed={() => (modalData = null)}/>
{/if}

<style lang="scss" scoped>
@import url("https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css");
</style>

1 change: 1 addition & 0 deletions src/elements/freeflow/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "./Freeflow.wc.svelte";
1 change: 1 addition & 0 deletions src/stores/solutionsList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ export const solutionList = {
nodepilot: "np",
fullvm: "fvm",
subsquid: "ss",
freeflow: 'ff',
algorand: "al",
};
54 changes: 54 additions & 0 deletions src/types/freeflow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {v4} from "uuid";
import {validateKey, validateKeyValue} from "../utils/validateName";
import {Network} from "./kubernetes";
import NodeID from "./nodeId";
import {Disk} from "./vm";

const NETWORK_NAME: string = 'TFNet'
const IP_RANGE: string = '10.249.0.0/16'

const DISK_NAME: string = 'disk'
const DISK_SIZE: number = 8;
const DISK_MOUNT_POINT: string = '/disk'

const VM_USE_PLANETARY: boolean = true;
const VM_USE_PUBLIC_IP: boolean = true;
const VM_CPU_COUNT: number = 1;
const VM_MEMORY_COUNT: number = 1024 * 2;
const VM_ROOT_FS_SIZE: number = 0;
const VM_ENTRY_POINT: string = '/init.sh'
const VM_FLIST = "https://hub.grid.tf/lennertapp2.3bot/threefoldjimber-freeflow-ssh-latest.flist"
const VM_ROOT_FS_EDITABLE = false;

export class Env {
constructor(public id = v4(), public key = "", public value = "") {
}

public get valid(): boolean {
const {key, value} = this;
return key !== "" && value !== "" && validateKey(key) === undefined && validateKeyValue(value) === undefined;
}
}


export default class FreeFlow {

constructor(public envs: Env[] = [],
public id = v4(),
public threeBotUserId = "",
public flist = VM_FLIST,
public pkg = "",
public cpu = VM_CPU_COUNT,
public disks: Disk[] = [new Disk(v4(), DISK_NAME, DISK_SIZE, DISK_MOUNT_POINT)],
public memory = VM_MEMORY_COUNT,
public entrypoint = VM_ENTRY_POINT,
public planetary = VM_USE_PLANETARY,
public nodeId: number = null,
public network = new Network(NETWORK_NAME, IP_RANGE),
public publicIp = VM_USE_PUBLIC_IP,
public selection = new NodeID(),
public rootFs = VM_ROOT_FS_SIZE,
public rootFsEditable = VM_ROOT_FS_EDITABLE
) {
}
}
Loading