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

Fix/remove service context #42

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
31 changes: 14 additions & 17 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import Alert from '@/components/alert/Alert';
import Loader from '@/components/loader/Loader';
import Nav from '@/components/nav/Nav';
import AlertProvider from '@/contexts/AlertContext';
import ServiceContextProvider from '@/contexts/ServiceContext';
import ThemeContextProvider from '@/contexts/ThemeContext';
import TimeContextProvider from '@/contexts/TimeContext';
import { useIsDesktop } from '@/hooks/useMediaQuery';
Expand All @@ -19,25 +18,23 @@ function App() {
<TimeContextProvider>
<ThemeContextProvider>
<AlertProvider>
<ServiceContextProvider>
<div className={`
<div className={`
${!isDesktop ? 'flex-col' : ''}
relative max-w-[1440px] mx-auto flex font-nunito-sans text-text-dark dark:text-text-white dark:bg-bg-dark-900
`
}>
<Nav />
<main className='mx-6 my-8 grow llg-w-[1146px] relative'>
{navigation.state === 'loading' ? (
<Loader />
) : (
<>
<Outlet />
<Alert />
</>
)}
</main>
</div>
</ServiceContextProvider>
}>
<Nav />
<main className='mx-6 my-8 grow llg-w-[1146px] relative'>
{navigation.state === 'loading' ? (
<Loader />
) : (
<>
<Outlet />
<Alert />
</>
)}
</main>
</div>
</AlertProvider>
</ThemeContextProvider>
</TimeContextProvider>
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/components/error-state/ErrorState.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import { useContext } from 'react';
import { twMerge } from 'tailwind-merge';

import Svg, { SvgNames } from '@/components/images/Svg';
import { ThemeContext } from '@/contexts/ThemeContext';

import styles from './error-state.module.scss';

interface InfoListErrorProps {
isPage?: boolean;
title?: string;
}

export default function ErrorState({ title }: InfoListErrorProps) {
export default function ErrorState({ title, isPage }: InfoListErrorProps) {
const { theme } = useContext(ThemeContext);
const svgName = theme === 'dark' ? SvgNames.InfoDark : SvgNames.Info;
const pageClassName = isPage ? 'rounded-3xl' : '';

return (
<div className='h-[319px] bg-white dark:bg-bg-dark-800 rounded-b-3xl flex flex-col items-center justify-center'>
<div className={`${twMerge('h-[319px] bg-white dark:bg-bg-dark-800 rounded-b-3xl flex flex-col items-center justify-center', pageClassName)}`}>
<Svg svgName={svgName} className={`rounded-full ${styles.svgFilter}`} sizeClass='w-[75px] h-[75px]' />
<p className='dark:text-text-white text-text-dark text-xl pt-9'>Failed to load {title?.toLowerCase() ?? 'data'}</p>
<p className='dark:text-text-white text-text-dark text-xl pt-9 p-3'>Failed to load {title?.toLowerCase() ?? 'data'}</p>
</div>
);
}
Expand Down
54 changes: 40 additions & 14 deletions frontend/src/components/tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import React from 'react';
import React, { PropsWithChildren } from 'react';
import { twMerge } from 'tailwind-merge';

import TooltipPrimitive from '@radix-ui/react-tooltip';
import {
Tooltip, TooltipContent as PrimitiveTooltipContent, TooltipProvider,
TooltipTrigger as PrimitiveTooltipTrigger
} from '@radix-ui/react-tooltip';

const TooltipProvider = TooltipPrimitive.Provider;

const Tooltip = TooltipPrimitive.Root;

const TooltipTrigger = TooltipPrimitive.Trigger;

const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
const NativeTooltipContent = React.forwardRef<
React.ElementRef<typeof PrimitiveTooltipContent>,
React.ComponentPropsWithoutRef<typeof PrimitiveTooltipContent>
>(({ className, sideOffset = 4, ...props }, ref) => (
<TooltipPrimitive.Content
<PrimitiveTooltipContent
ref={ref}
sideOffset={sideOffset}
className={twMerge(
Expand All @@ -24,6 +21,35 @@ const TooltipContent = React.forwardRef<
/>
));

TooltipContent.displayName = TooltipPrimitive.Content.displayName;
TooltipContent.displayName = PrimitiveTooltipContent.displayName;

function TooltipContent({ children }: PropsWithChildren) {
return (
<NativeTooltipContent sideOffset={10} className='w-[232px] dark:bg-bg-dark-600 bg-white border border-text-white-600 dark:border-none whitespace-normal rounded-3xl text-center shadow-sm py-4 px-3 leading-tight'>
{children}
{/* <p>The top x master candidates are in the current master committee with equal voting power</p> */}
</NativeTooltipContent>
);
}

interface TooltipTriggerProps extends PropsWithChildren {
withQuestionMark?: boolean;
}

function TooltipTrigger({ children, withQuestionMark }: TooltipTriggerProps) {
function TooltipQuestionMark() {
return (
<span className='w-4 h-4 text-xs inline-flex items-center justify-center rounded-full dark:bg-bg-dark-600 bg-bg-white-1000 text-primary dark:text-white md:ml-1.5 ml-1'>
?
</span>
);
}

return (
<PrimitiveTooltipTrigger>
{children}{withQuestionMark ? <TooltipQuestionMark /> : ''}
</PrimitiveTooltipTrigger>
);
}

export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
export { Tooltip, TooltipProvider, TooltipTrigger, TooltipContent };
15 changes: 0 additions & 15 deletions frontend/src/contexts/ServiceContext.tsx

This file was deleted.

16 changes: 0 additions & 16 deletions frontend/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,6 @@ import App from './App.tsx';

import '@/index.css';

async function managementLoader() {
// async function getData() {
// TODO: This is broken without the new api
// const response = await axios.get(`${baseUrl}/information/newAPI`);
// return response.data;
// }

// const data = await getData();

return {
minimumDelegation: 0,
grandmasterRemainingBalance: 0
};
}

export async function appLoader() {
async function getData() {
const response = await axios.get(`${baseUrl}/information/network`);
Expand Down Expand Up @@ -96,7 +81,6 @@ const router = createBrowserRouter([
}, {
path: 'managementMasterCommittee',
element: <ManagementMasterCommitteePage />,
loader: managementLoader
}, {
path: '*',
element: <Navigate to='/home' replace />,
Expand Down
13 changes: 6 additions & 7 deletions frontend/src/pages/management-login-page/ManagementLoginPage.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { useContext, useEffect, useState } from 'react';
import { useEffect, useState } from 'react';

import Button from '@/components/button/Button';
import Card from '@/components/card/Card';
import ErrorState from '@/components/error-state/ErrorState';
import InfoList from '@/components/info-list/InfoList';
import Loader from '@/components/loader/Loader';
import { ServiceContext } from '@/contexts/ServiceContext';
import LoginError from '@/pages/management-login-page/components/LoginError';
import { AccountDetails } from '@/services/grandmaster-manager';
import { AccountDetails, GrandMasterManager } from '@/services/grandmaster-manager';
import { TableContent } from '@/types/managementLoginPage';
import { formatHash } from '@/utils/formatter';

Expand All @@ -18,8 +17,6 @@ export default function ManagementLoginPage() {
const [tableContent, setTableContent] = useState<TableContent | null>();
const [isLoading, setIsLoading] = useState(true);

const service = useContext(ServiceContext);

function getContent(accountDetails: AccountDetails): TableContent {
const { accountAddress, balance, denom, networkId, rpcUrl } = accountDetails;

Expand Down Expand Up @@ -48,6 +45,8 @@ export default function ManagementLoginPage() {
async function getData() {
try {
setIsLoading(true);
const service = new GrandMasterManager();

const result = await service?.login();
if (!result || !service) {
setTableContent(null);
Expand All @@ -64,7 +63,7 @@ export default function ManagementLoginPage() {
}

getData();
}, [service]);
}, []);

if (isLoading) {
return <Loader />;
Expand All @@ -75,7 +74,7 @@ export default function ManagementLoginPage() {
}

if (!tableContent) {
return <ErrorState title='master login' />;
return <ErrorState isPage title='master login' />;
}

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,49 @@
import { useContext, useEffect, useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';

import Button from '@/components/button/Button';
import Card from '@/components/card/Card';
import { Cell } from '@/components/cell/Cell';
import Dialog, { DialogRef, DialogResultBase } from '@/components/dialog/Dialog';
import ErrorState from '@/components/error-state/ErrorState';
import Loader from '@/components/loader/Loader';
import { ServiceContext } from '@/contexts/ServiceContext';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/tooltip/Tooltip';
import AddMasterNodeDialog from '@/pages/management-master-committee-page/components/add-master-node-dialog/AddMasterNodeDialog';
import {
NoLoginDialog
} from '@/pages/management-master-committee-page/components/no-login-dialog/NoLoginDialog';
import PromoteDialog from '@/pages/management-master-committee-page/components/promote-dialog/PromoteDialog';
import RemoveMasterNodeDialog from '@/pages/management-master-committee-page/components/remove-master-node-dialog/RemoveMasterNodeDialog';
import { CandidateDetailsStatus } from '@/services/grandmaster-manager/statsServiceClient';
import { AccountDetails, getCandidates, GrandMasterManager } from '@/services/grandmaster-manager';
import { ManagerError } from '@/services/grandmaster-manager/errors';
import { TableContent } from '@/types/managementMasterCommitteePage';
import { CandidateDetailsStatus } from '@/services/grandmaster-manager/statsServiceClient';
import { formatHash } from '@/utils/formatter';
import { Tooltip, TooltipContent, TooltipTrigger } from '@radix-ui/react-tooltip';

import type { TableContent } from '@/types/managementMasterCommitteePage';
export default function ManagementMasterCommitteePage() {
const [isLoading, setIsLoading] = useState<boolean>(true);
const [tableContent, setTableContent] = useState<TableContent | null>();
const [dialogContent, setDialogContent] = useState<React.ReactNode | null>(null);
const [dialogResult, setDialogResult] = useState<DialogResultBase>();
const [error, setError] = useState<ManagerError>();
const [accountDetails, setAccountDetails] = useState<AccountDetails>();

const service = useContext(ServiceContext);
const dialogRef = useRef<DialogRef>(null);

useEffect(() => {
async function fetchData() {
try {
setIsLoading(true);
const candidates = await service?.getCandidates();

const candidates = await getCandidates();

// try login, use view-only mode if can not login
try {
const service = new GrandMasterManager();
const accountDetails = await service.login();
setAccountDetails(accountDetails);
} catch (error) {
console.log('no login info, entering view-only mode');
}

if (!candidates) {
setTableContent(null);
Expand All @@ -44,20 +57,21 @@ export default function ManagementMasterCommitteePage() {
width: 'w-[220px]'
}, {
id: 'delegation',
name: 'Delegation',
name: (
<Tooltip>
<TooltipTrigger withQuestionMark>Delegation</TooltipTrigger>
<TooltipContent>
<p>The number is rounded down to 6 decimal places</p>
</TooltipContent>
</Tooltip>
),
width: 'w-[220px]'
},
{
}, {
id: 'rank',
name: (
<Tooltip>
<TooltipTrigger>
Rank
<span className='w-4 h-4 text-xs inline-flex items-center justify-center rounded-full dark:bg-bg-dark-600 bg-bg-white-1000 text-primary dark:text-white md:ml-1.5 ml-1'>
?
</span>
</TooltipTrigger>
<TooltipContent sideOffset={10} className='w-[232px] dark:bg-bg-dark-600 bg-white border border-text-white-600 dark:border-none whitespace-normal rounded-3xl text-center shadow-sm py-4 px-3 leading-tight'>
<TooltipTrigger withQuestionMark>Rank</TooltipTrigger>
<TooltipContent>
<p>The top x master candidates are in the current master committee with equal voting power</p>
</TooltipContent>
</Tooltip>
Expand Down Expand Up @@ -85,9 +99,15 @@ export default function ManagementMasterCommitteePage() {
}

fetchData(); // Call the asynchronous function to fetch the data
}, [service]);
}, []);

function openDialog(content: React.ReactNode) {
if (!accountDetails) {
setDialogContent(<NoLoginDialog closeDialog={handleCloseDialog} />);
dialogRef.current?.open();
return;
}

setDialogContent(content);
dialogRef.current?.open();
}
Expand Down Expand Up @@ -120,7 +140,7 @@ export default function ManagementMasterCommitteePage() {

if (error?.errorType) {
return (
<ErrorState title={`master candidate list - ${error.message}`} />
<ErrorState isPage title={`master candidate list - ${error.message}`} />
);
}

Expand All @@ -138,7 +158,7 @@ export default function ManagementMasterCommitteePage() {
<div className='self-end'>
<Button
colour='primary'
onClick={() => openDialog(<AddMasterNodeDialog closeDialog={handleCloseDialog} setDialogResult={setDialogResult} />)}
onClick={() => openDialog(<AddMasterNodeDialog accountDetails={accountDetails} closeDialog={handleCloseDialog} setDialogResult={setDialogResult} />)}
>
Add a new master candidate
</Button>
Expand All @@ -164,15 +184,15 @@ export default function ManagementMasterCommitteePage() {
variant='outlined'
colour='success'
className='px-4'
onClick={() => openDialog(<PromoteDialog closeDialog={handleCloseDialog} data={row} type='promote' setDialogResult={setDialogResult} />)}
onClick={() => openDialog(<PromoteDialog accountDetails={accountDetails} closeDialog={handleCloseDialog} data={row} type='promote' setDialogResult={setDialogResult} />)}
>
Promote
</Button>
<Button
variant='outlined'
colour='warning'
className='px-4 ml-2'
onClick={() => openDialog(<PromoteDialog closeDialog={handleCloseDialog} data={row} type='demote' setDialogResult={setDialogResult} />)}
onClick={() => openDialog(<PromoteDialog accountDetails={accountDetails} closeDialog={handleCloseDialog} data={row} type='demote' setDialogResult={setDialogResult} />)}
>
Demote
</Button>
Expand Down
Loading