Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(provider): control-machine add/edit - online/offline functionality #447

Merged
merged 51 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
ebe6471
added server-access and server-form files
jigar-arc10 Aug 22, 2024
6342ed9
added wallet import page - wip, fixed issue with file upload in serve…
jigar-arc10 Aug 23, 2024
7f89ed8
added become-provider steps ui
jigar-arc10 Aug 29, 2024
58055d7
server access step added with state support
jigar-arc10 Sep 18, 2024
192d116
added provider config and provider attribute screen
jigar-arc10 Sep 19, 2024
da07743
added provider process with hoc to prevent access to pages
jigar-arc10 Oct 7, 2024
329e06c
added progress for becoming prvider for final stage
jigar-arc10 Oct 8, 2024
51e5ef0
Code clean up and added navigation logic to homecontainer
jigar-arc10 Oct 10, 2024
c977e2e
package lock updated
jigar-arc10 Oct 10, 2024
66d0f11
fixed package-lock.json merge issue
jigar-arc10 Oct 10, 2024
25ed729
more cleanup and remove general warnings
jigar-arc10 Oct 10, 2024
897066e
removed unused npm package
jigar-arc10 Oct 10, 2024
aefe70b
fix minor error on api
jigar-arc10 Oct 11, 2024
8e5eb6a
Added dashboard and actions page
jigar-arc10 Oct 11, 2024
ea30723
change status api endpoint
jigar-arc10 Oct 11, 2024
d024c0d
Merge branch 'feature/provider-console/become-provider-process' into …
jigar-arc10 Oct 11, 2024
ead4eac
added stat line and pie charts
jigar-arc10 Oct 11, 2024
f5c243f
Added console apis to get dashboard data and show appropriate details
jigar-arc10 Oct 11, 2024
4472dbd
fixed actions and changed home component
jigar-arc10 Oct 12, 2024
8df762a
token varification and refresh token fix
jigar-arc10 Oct 15, 2024
d4288b3
changed wallet connect from wallet status to wallet provider
jigar-arc10 Oct 15, 2024
6e8b289
fixed issue in loading provider status
jigar-arc10 Oct 16, 2024
44934ae
fixed home loading issue
jigar-arc10 Oct 16, 2024
d91d340
fixed refresh token, added disabled menu items
jigar-arc10 Oct 16, 2024
fd62ae2
fixed build process
jigar-arc10 Oct 16, 2024
3276a95
feat(provider): added sentry and docker
jigar-arc10 Oct 17, 2024
8f123e1
fix(provider): fixed wallet switching and getting status
jigar-arc10 Oct 18, 2024
5fa9f63
feat(provider): reduced number of events in dashboard
jigar-arc10 Oct 18, 2024
2b0d5e0
feat(provider): added docker compose changes for provider-console
jigar-arc10 Oct 18, 2024
781a99c
feat(provider): added deployments and deployment detail page
jigar-arc10 Oct 18, 2024
ee5d564
fix(provider): change hours to seconds for calculation purpose)
jigar-arc10 Oct 18, 2024
7057434
feat(provider): added auth for deployments and deployment details page
jigar-arc10 Oct 18, 2024
8648e13
feat(provider): added env and removed settingsprovider
jigar-arc10 Oct 29, 2024
f1637fd
fix(provider): fix lint errors and removed console.logs
jigar-arc10 Oct 29, 2024
614c4ba
fix(provider): become-provider looped, fixed it
jigar-arc10 Oct 30, 2024
5d08b82
fix(provider): router and reset process fixed
jigar-arc10 Oct 30, 2024
1110b35
fix(provider): removed Get Started button for now
jigar-arc10 Oct 30, 2024
f2696bf
fix(provider): removed unused import in nav
jigar-arc10 Oct 30, 2024
7344be9
fix(provider): change functions to react fc component
jigar-arc10 Oct 30, 2024
7f9da2b
fix(provider): fix lint issues
jigar-arc10 Oct 30, 2024
c9df37a
fix(provider): change functions to react fc component
jigar-arc10 Oct 31, 2024
1f2d277
fix(provider): rebased main
jigar-arc10 Oct 31, 2024
a97c913
fix(provider): added docker build and fix build related issues
jigar-arc10 Nov 5, 2024
91e8bcd
feat(provider): control machine edit, add from sidebar
jigar-arc10 Nov 5, 2024
f4629af
fix(provider): control machine auto connect on page load
jigar-arc10 Nov 5, 2024
3811d55
fix(provider): fix loading not showing while connecting provider cont…
jigar-arc10 Nov 6, 2024
226e744
fix(provider): close drawer on successfull connection
jigar-arc10 Nov 6, 2024
4927267
feat(provider): change favicon to akash favicon
jigar-arc10 Nov 6, 2024
13c537b
Merge branch 'main' into feature/provider/control-machine
jigar-arc10 Nov 14, 2024
eeb82b8
fix(provider): merge issues with main
jigar-arc10 Nov 14, 2024
6bf0dfc
chore: removed comments
jigar-arc10 Nov 26, 2024
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
Binary file modified apps/provider-console/public/favicon.ico
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { useAtom } from "jotai/react";
import { z } from "zod";

import { useControlMachine } from "@src/context/ControlMachineProvider";
import { useWallet } from "@src/context/WalletProvider";
import providerProcessStore from "@src/store/providerProcessStore";
import { ControlMachineWithAddress } from "@src/types/controlMachine";
import restClient from "@src/utils/restClient";
import { ResetProviderForm } from "./ResetProviderProcess";

Expand Down Expand Up @@ -55,12 +58,16 @@ type AccountFormValues = z.infer<typeof accountFormSchema>;
interface ServerFormProp {
currentServerNumber: number;
onComplete: () => void;
editMode?: boolean;
controlMachine?: ControlMachineWithAddress | null;
}

export const ServerForm: React.FC<ServerFormProp> = ({ currentServerNumber, onComplete }) => {
export const ServerForm: React.FC<ServerFormProp> = ({ currentServerNumber, onComplete, editMode = false, controlMachine }) => {
const [providerProcess, setProviderProcess] = useAtom(providerProcessStore.providerProcessAtom);
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const [storedFileContent, setStoredFileContent] = useState<string | null>(null);
const { setControlMachine } = useControlMachine();
const { address } = useWallet();

const getDefaultValues = () => {
if (currentServerNumber === 0 || !providerProcess?.storeInformation) {
Expand All @@ -84,18 +91,18 @@ export const ServerForm: React.FC<ServerFormProp> = ({ currentServerNumber, onCo

const form = useForm<AccountFormValues>({
resolver: zodResolver(accountFormSchema),
defaultValues: getDefaultValues() as any
defaultValues: editMode ? controlMachine?.access : (getDefaultValues() as any)
});

useEffect(() => {
if (currentServerNumber > 0 && providerProcess?.storeInformation) {
const firstServer = providerProcess.machines[0]?.access;
if (firstServer.file) {
const firstServer = editMode ? controlMachine?.access : providerProcess.machines[0]?.access;
if (firstServer?.file) {
setStoredFileContent(typeof firstServer.file === "string" ? firstServer.file : null);
form.setValue("authType", "file");
}
}
}, [currentServerNumber, providerProcess, form]);
}, [currentServerNumber, providerProcess, form, editMode, controlMachine]);

const [verificationError, setVerificationError] = useState<{ message: string; details: string[] } | null>(null);
const [, setVerificationResult] = useState(null);
Expand Down Expand Up @@ -127,7 +134,7 @@ export const ServerForm: React.FC<ServerFormProp> = ({ currentServerNumber, onCo
}

let response: any;
if (currentServerNumber === 0) {
if (currentServerNumber === 0 || editMode) {
response = await restClient.post("/verify/control-machine", jsonData, {
headers: { "Content-Type": "application/json" }
});
Expand All @@ -152,21 +159,29 @@ export const ServerForm: React.FC<ServerFormProp> = ({ currentServerNumber, onCo
}

if (response.status === "success") {
const machines = [...(providerProcess?.machines ?? [])];
machines[currentServerNumber] = {
const machine = {
access: {
...formValues,
file: formValues.file && formValues.file[0] ? await readFileAsBase64(formValues.file[0]) : storedFileContent
},
systemInfo: response.data.system_info
};
if (!editMode) {
const machines = [...(providerProcess?.machines ?? [])];
machines[currentServerNumber] = machine;

setProviderProcess({
...providerProcess,
machines,
storeInformation: currentServerNumber === 0 ? formValues.saveInformation : providerProcess?.storeInformation,
process: providerProcess.process
});
setProviderProcess({
...providerProcess,
machines,
storeInformation: currentServerNumber === 0 ? formValues.saveInformation : providerProcess?.storeInformation,
process: providerProcess.process
});
} else {
setControlMachine({
address,
...machine
});
}
onComplete();
}
} catch (error: any) {
Expand Down Expand Up @@ -206,10 +221,9 @@ export const ServerForm: React.FC<ServerFormProp> = ({ currentServerNumber, onCo
<div className="space-y-6">
<div>
<h3 className="text-xl font-bold">
{currentServerNumber === 0 && "Control Plane Machine Access"}
{currentServerNumber !== 0 && "Node Access"}
{editMode ? "Control Machine Access" : currentServerNumber === 0 ? "Control Plane Machine Access" : "Node Access"}
</h3>
<p className="text-muted-foreground text-sm">Enter the required details for your control plane setup</p>
<p className="text-muted-foreground text-sm">Enter the required details for your {editMode ? "control machine" : "control plane setup"}</p>
</div>
<div>
<Separator />
Expand Down Expand Up @@ -345,16 +359,16 @@ export const ServerForm: React.FC<ServerFormProp> = ({ currentServerNumber, onCo
</div>
<div className="flex justify-end">
<div className="flex w-full justify-between">
<div className="flex justify-start">
<ResetProviderForm />
</div>
<div className="flex justify-start">{!editMode && <ResetProviderForm />}</div>
<div className="flex justify-end">
<Button type="submit" disabled={isVerifying}>
{isVerifying ? (
<>
<Spinner />
Verifying...
</>
) : editMode ? (
"Update"
) : (
"Next"
)}
Expand All @@ -379,7 +393,7 @@ export const ServerForm: React.FC<ServerFormProp> = ({ currentServerNumber, onCo
</Alert>
)}
</div>
{currentServerNumber === 0 && (
{currentServerNumber === 0 && !editMode && (
<div className="rounded-md border">
<div className="space-y-2 p-4">
<h4 className="text-lg font-bold">Heads up!</h4>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ import { useAtom } from "jotai";
import { useRouter } from "next/router";
import { z } from "zod";

import { useControlMachine } from "@src/context/ControlMachineProvider";
import { useWallet } from "@src/context/WalletProvider";
import providerProcessStore from "@src/store/providerProcessStore";
import { ControlMachineWithAddress } from "@src/types/controlMachine";
import restClient from "@src/utils/restClient";
import { ResetProviderForm } from "./ResetProviderProcess";

Expand Down Expand Up @@ -77,6 +80,8 @@ export const WalletImport: React.FC<WalletImportProps> = ({ onComplete }) => {

const [providerProcess] = useAtom(providerProcessStore.providerProcessAtom);
const [, resetProviderProcess] = useAtom(providerProcessStore.resetProviderProcess);
const { setControlMachine } = useControlMachine();
const { address } = useWallet();

const defaultValues: Partial<AppearanceFormValues> = {
walletMode: "seed"
Expand All @@ -95,51 +100,58 @@ export const WalletImport: React.FC<WalletImportProps> = ({ onComplete }) => {
};

const submitForm = async (data: SeedFormValues) => {
if (!providerProcess.machines || providerProcess.machines.length === 0) {
setError("No machine information available");
}
setIsLoading(true);
setError(null);
try {
const publicKey = providerProcess.machines[0].systemInfo.public_key;
const keyId = providerProcess.machines[0].systemInfo.key_id;
const encryptedSeedPhrase = await encrypt(data.seedPhrase, publicKey);
if (providerProcess.machines && providerProcess.machines.length > 0) {
const publicKey = providerProcess.machines[0].systemInfo.public_key;
const keyId = providerProcess.machines[0].systemInfo.key_id;
const encryptedSeedPhrase = await encrypt(data.seedPhrase, publicKey);

const finalRequest = {
wallet: {
key_id: keyId,
wallet_phrase: encryptedSeedPhrase
},
nodes: providerProcess.machines.map(machine => ({
hostname: machine.access.hostname,
port: machine.access.port,
username: machine.access.username,
keyfile: machine.access.file,
password: machine.access.password,
install_gpu_drivers: machine.systemInfo.gpu.count > 0 ? true : false
})),
provider: {
attributes: providerProcess.attributes,
pricing: providerProcess.pricing,
config: providerProcess.config
}
};
const finalRequest = {
wallet: {
key_id: keyId,
wallet_phrase: encryptedSeedPhrase
},
nodes: providerProcess.machines.map(machine => ({
hostname: machine.access.hostname,
port: machine.access.port,
username: machine.access.username,
keyfile: machine.access.file,
password: machine.access.password,
install_gpu_drivers: machine.systemInfo.gpu.count > 0 ? true : false
})),
provider: {
attributes: providerProcess.attributes,
pricing: providerProcess.pricing,
config: providerProcess.config
}
};

const response: any = await restClient.post("/build-provider", finalRequest, {
headers: { "Content-Type": "application/json" }
});
const response: any = await restClient.post("/build-provider", finalRequest, {
headers: { "Content-Type": "application/json" }
});

if (response.action_id) {
resetProviderProcess();
router.push(`/action?id=${response.action_id}`);
if (response.action_id) {
const machineWithAddress: ControlMachineWithAddress = {
address: address,
...providerProcess.machines[0]
};
await setControlMachine(machineWithAddress);
resetProviderProcess();
router.push(`/action?id=${response.action_id}`);
} else {
throw new Error("Invalid response from server");
}
} else {
throw new Error("Invalid response from server");
throw new Error("No machine information available");
}
} catch (error) {
console.error("Error during wallet verification:", error);
setError("An error occurred while processing your request. Please try again.");
} finally {
onComplete();
setIsLoading(false);
onComplete();
}
};

Expand Down
8 changes: 2 additions & 6 deletions apps/provider-console/src/components/home/HomeContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,10 @@ import { WalletNotConnected } from "./WalletNotConnected";

export const HomeContainer: React.FC = () => {
const router = useRouter();
const { isWalletConnected, isWalletArbitrarySigned, isProvider, isOnline, isProviderStatusFetched } = useWallet();
const [isLoading, setIsLoading] = useState(false);
const { isWalletConnected, isProvider, isOnline, isProviderStatusFetched } = useWallet();
const [isLoading] = useState(false);
const { data: providerActions } = useProviderActions();

useEffect(() => {
setIsLoading(true);
}, [isProvider, isOnline, isWalletArbitrarySigned]);

useEffect(() => {
if (isWalletConnected && isProvider) {
router.push("/dashboard");
Expand Down
38 changes: 36 additions & 2 deletions apps/provider-console/src/components/layout/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";
import React, { ReactNode, useState } from "react";
import { Button, buttonVariants } from "@akashnetwork/ui/components";
import { Button, buttonVariants, Spinner } from "@akashnetwork/ui/components";
import Drawer from "@mui/material/Drawer";
import { useTheme as useMuiTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
Expand All @@ -10,6 +10,7 @@ import getConfig from "next/config";
import Image from "next/image";
import Link from "next/link";

import { useControlMachine } from "@src/context/ControlMachineProvider";
import { useWallet } from "@src/context/WalletProvider";
import { ISidebarGroupMenu } from "@src/types";
import { closedDrawerWidth, drawerWidth } from "@src/utils/constants";
Expand All @@ -35,6 +36,8 @@ export const Sidebar: React.FC<Props> = ({ isMobileOpen, handleDrawerToggle, isN
const muiTheme = useMuiTheme();
const smallScreen = useMediaQuery(muiTheme.breakpoints.down("md"));

const { activeControlMachine, openControlMachineDrawer, controlMachineLoading } = useControlMachine();

const routeGroups: ISidebarGroupMenu[] = [
{
hasDivider: false,
Expand Down Expand Up @@ -162,6 +165,37 @@ export const Sidebar: React.FC<Props> = ({ isMobileOpen, handleDrawerToggle, isN
{_isNavOpen && (
<div className="space-y-2 pb-4 pl-4 pr-4">
{/* <NodeStatusBar /> */}
{controlMachineLoading ? (
<div className="flex flex-col space-y-2">
<div className="text-muted-foreground flex items-center gap-2 text-sm">
Machine:
<div className="relative flex items-center gap-2">
<Spinner size="small" />
<div className="text-xs">Connecting...</div>
</div>
</div>
</div>
) : activeControlMachine ? (
<div className="flex flex-col space-y-2">
<div className="text-muted-foreground hover:text-foreground flex cursor-pointer items-center gap-2 text-sm" onClick={openControlMachineDrawer}>
Machine:
<div className="relative flex items-center gap-2">
<div className="h-2 w-2 rounded-full bg-green-500" />
{activeControlMachine.access.hostname}
</div>
</div>
</div>
) : (
<div className="flex flex-col space-y-2">
<div className="text-muted-foreground hover:text-foreground flex cursor-pointer items-center gap-2 text-sm" onClick={openControlMachineDrawer}>
Machine:
<div className="relative flex items-center gap-2">
<div className="h-2 w-2 rounded-full bg-red-500" />
<div className="roundedpx-2 py-1 text-xs">Not Connected</div>
</div>
</div>
</div>
)}

<div className="flex items-center justify-center space-x-1 pt-4">
<Link
Expand Down Expand Up @@ -228,7 +262,7 @@ export const Sidebar: React.FC<Props> = ({ isMobileOpen, handleDrawerToggle, isN

return (
<nav
className={cn("ease bg-header/95 fixed z-[100] md:flex-shrink-0", {
className={cn("ease bg-header/95 fixed md:flex-shrink-0", {
["md:w-[240px]"]: _isNavOpen || isHovering,
["md:w-[57px]"]: !(_isNavOpen || isHovering)
})}
Expand Down
Loading