Skip to content

Commit

Permalink
Merge pull request #819 from alleslabs/feature/cfe-34-validator-desc
Browse files Browse the repository at this point in the history
[CFE-33,34]: Feat - validator details overview section
  • Loading branch information
evilpeach committed Mar 15, 2024
2 parents 303fcd3 + ca268a7 commit 2de4564
Show file tree
Hide file tree
Showing 18 changed files with 421 additions and 227 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- [#819](https://github.com/alleslabs/celatone-frontend/pull/819) Add validator detail overview section with data from APIs
- [#821](https://github.com/alleslabs/celatone-frontend/pull/821) Add Validator's proposed blocks table
- [#818](https://github.com/alleslabs/celatone-frontend/pull/818) bonded tokens voting powers replacement with real data from api v1
- [#801](https://github.com/alleslabs/celatone-frontend/pull/801) Add validator detail ui structure
Expand Down
72 changes: 23 additions & 49 deletions src/lib/components/ValidatorBadge.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { ImageProps } from "@chakra-ui/react";
import { Flex, Image, Spinner, Text } from "@chakra-ui/react";
import { Flex, Text } from "@chakra-ui/react";

import { useMobile } from "lib/app-provider";
import { ExplorerLink } from "lib/components/ExplorerLink";
import { useValidatorImage } from "lib/services/validatorService";
import type { Nullable, Validator } from "lib/types";

import { MobileLabel } from "./table/MobileLabel";
import { ValidatorImage } from "./ValidatorImage";

interface ValidatorBadgeProps {
validator: Nullable<Validator>;
Expand All @@ -17,24 +17,6 @@ interface ValidatorBadgeProps {
moreInfo?: JSX.Element;
}

const FallbackRender = ({
badgeSize,
}: {
badgeSize: ValidatorBadgeProps["badgeSize"];
}) => (
<>
<Image
boxSize={badgeSize}
src="https://raw.githubusercontent.com/alleslabs/assets/main/webapp-assets/asset/na-token.svg"
alt="N/A"
borderRadius="50%"
/>
<Text variant="body2" color="text.disabled">
N/A
</Text>
</>
);

export const ValidatorBadge = ({
validator,
badgeSize = 10,
Expand All @@ -43,41 +25,33 @@ export const ValidatorBadge = ({
hasLabel = true,
moreInfo,
}: ValidatorBadgeProps) => {
const { data: valImgSrc, isLoading } = useValidatorImage(validator);
const isMobile = useMobile();

return (
<Flex alignItems="center" gap={2}>
<ValidatorImage validator={validator} boxSize={badgeSize} />
{validator ? (
<Flex direction="column">
{isMobile && hasLabel && <MobileLabel label="Validator" />}
<ExplorerLink
value={validator.moniker ?? validator.validatorAddress}
copyValue={validator.validatorAddress}
type="validator_address"
textFormat="ellipsis"
showCopyOnHover
ampCopierSection={ampCopierSection}
maxWidth={maxWidth}
fixedHeight
/>
{moreInfo}
</Flex>
) : (
<>
{isLoading ? (
<Spinner boxSize={badgeSize} />
) : (
<Image
boxSize={badgeSize}
src={valImgSrc}
alt={validator.moniker}
borderRadius="50%"
fallbackSrc="https://assets.alleslabs.dev/webapp-assets/placeholder/validator.svg"
fallbackStrategy="beforeLoadOrError"
/>
)}
<Flex direction="column">
{isMobile && hasLabel && <MobileLabel label="Validator" />}
<ExplorerLink
value={validator.moniker ?? validator.validatorAddress}
copyValue={validator.validatorAddress}
type="validator_address"
textFormat="ellipsis"
showCopyOnHover
ampCopierSection={ampCopierSection}
maxWidth={maxWidth}
fixedHeight
/>
{moreInfo}
</Flex>
<ValidatorImage validator={validator} boxSize={badgeSize} />
<Text variant="body2" color="text.disabled">
N/A
</Text>
</>
) : (
<FallbackRender badgeSize={badgeSize} />
)}
</Flex>
);
Expand Down
43 changes: 43 additions & 0 deletions src/lib/components/ValidatorImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { ImageProps } from "@chakra-ui/react";
import { Image, SkeletonCircle } from "@chakra-ui/react";

import { useValidatorImage } from "lib/services/validatorService";
import type { Nullable, Validator } from "lib/types";

interface ValidatorImageProps {
validator: Nullable<Validator>;
boxSize?: ImageProps["boxSize"];
}

export const ValidatorImage = ({
validator,
boxSize = 10,
}: ValidatorImageProps) => {
const { data, isLoading } = useValidatorImage(validator);

if (!validator) {
return (
<Image
boxSize={boxSize}
minWidth={boxSize}
src="https://raw.githubusercontent.com/alleslabs/assets/main/webapp-assets/asset/na-token.svg"
alt="N/A"
borderRadius="50%"
/>
);
}

return isLoading || !data || !validator.moniker ? (
<SkeletonCircle boxSize={boxSize} />
) : (
<Image
boxSize={boxSize}
minWidth={boxSize}
src={data}
alt={validator.moniker}
borderRadius="50%"
fallbackSrc="https://assets.alleslabs.dev/webapp-assets/placeholder/validator.svg"
fallbackStrategy="beforeLoadOrError"
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ import { Box, Flex, Heading, Text } from "@chakra-ui/react";
import type { BigSource } from "big.js";
import type { ScriptableContext, TooltipModel } from "chart.js";

import { useCelatoneApp } from "lib/app-provider";
import { LineChart } from "lib/components/chart/LineChart";
import { Loading } from "lib/components/Loading";
import { ErrorFetching } from "lib/components/state";
import { useAssetInfos } from "lib/services/assetService";
import { useValidatorHistoricalPowers } from "lib/services/validatorService";
import type { Token, U, ValidatorAddr } from "lib/types";
import type { AssetInfos, Option, Token, U, ValidatorAddr } from "lib/types";
import {
formatHHmm,
formatUTokenWithPrecision,
Expand All @@ -17,24 +15,19 @@ import {

interface VotingPowerChartProps {
validatorAddress: ValidatorAddr;
singleStakingDenom: Option<string>;
assetInfos: Option<AssetInfos>;
}

export const VotingPowerChart = ({
validatorAddress,
singleStakingDenom,
assetInfos,
}: VotingPowerChartProps) => {
const {
chainConfig: {
extra: { singleStakingDenom },
},
} = useCelatoneApp();
const { data: assetInfos, isLoading: isAssetInfosLoading } = useAssetInfos({
withPrices: false,
});

const { data: historicalPowers, isLoading } =
useValidatorHistoricalPowers(validatorAddress);

if (isLoading || isAssetInfosLoading) return <Loading />;
if (isLoading) return <Loading />;
if (!historicalPowers) return <ErrorFetching dataName="historical powers" />;

const labels = historicalPowers?.items.map((item) =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
import { Flex } from "@chakra-ui/react";

import { RelatedTransactionTable } from "../tables/RelatedTransactionsTable";
import type { ValidatorAddr } from "lib/types";
import type { AssetInfos, Option, ValidatorAddr } from "lib/types";

import { VotingPowerChart } from "./VotingPowerChart";

interface BondedTokenChangesProps {
validatorAddress: ValidatorAddr;
singleStakingDenom: Option<string>;
assetInfos: Option<AssetInfos>;
}

export const BondedTokenChanges = ({
validatorAddress,
}: BondedTokenChangesProps) => {
return (
<Flex direction="column" gap={{ base: 4, md: 8 }} pt={6}>
<VotingPowerChart validatorAddress={validatorAddress} />
<RelatedTransactionTable />
</Flex>
);
};
singleStakingDenom,
assetInfos,
}: BondedTokenChangesProps) => (
<Flex direction="column" gap={{ base: 4, md: 8 }} pt={6}>
<VotingPowerChart
validatorAddress={validatorAddress}
singleStakingDenom={singleStakingDenom}
assetInfos={assetInfos}
/>
<RelatedTransactionTable />
</Flex>
);
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import { Flex, Heading, Text } from "@chakra-ui/react";
import { Flex, Text } from "@chakra-ui/react";

export const ValidatorDescription = () => (
<Flex direction="column" gap={2}>
<Heading variant="h6" as="h6" color="text.main">
interface ValidatorDescriptionProps {
details: string;
}

export const ValidatorDescription = ({
details,
}: ValidatorDescriptionProps) => (
<Flex
direction="column"
gap={2}
backgroundColor="gray.900"
p={{ base: 4, md: 6 }}
rounded={8}
w="100%"
>
<Text variant="body2" fontWeight={500} as="h6" color="text.dark">
Validator Description
</Heading>
<Text variant="body1" color="text.main">
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam ad vel
assumenda, temporibus maiores quidem quibusdam sapiente expedita officiis
minus! Officiis itaque nisi reprehenderit tempora eaque eos quam, in
excepturi.
</Text>
<Text variant="body2" color="text.main">
{details}
</Text>
</Flex>
);
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { RecentBlocksSection } from "../performance/RecentBlocksSection";
import { UptimeSection } from "../performance/UptimeSection";
import { ProposedBlocksTable } from "../tables/ProposedBlocksTable";
import { VotedProposalsTable } from "../tables/VotedProposalsTable";
import { useMobile, useMoveConfig } from "lib/app-provider";
import { useMobile } from "lib/app-provider";
import { CustomIcon } from "lib/components/icon";
import { EmptyState } from "lib/components/state";
import type { ValidatorAddr } from "lib/types";
import type { AssetInfos, Option, ValidatorAddr } from "lib/types";

import { ValidatorDescription } from "./ValidatorDescription";
import { VotingPowerOverview } from "./VotingPowerOverview";
Expand All @@ -18,64 +18,67 @@ interface ValidatorOverviewProps {
onSelectVotes: () => void;
onSelectPerformance: () => void;
onSelectBondedTokenChanges: () => void;
isActive: boolean;
isJailed: boolean;
details: string;
validatorAddress: ValidatorAddr;
singleStakingDenom: Option<string>;
assetInfos: Option<AssetInfos>;
}

export const ValidatorOverview = ({
onSelectVotes,
onSelectPerformance,
onSelectBondedTokenChanges,
isActive,
isJailed,
details,
validatorAddress,
singleStakingDenom,
assetInfos,
}: ValidatorOverviewProps) => {
const isMobile = useMobile();
const move = useMoveConfig({ shouldRedirect: false });

return (
<>
<Flex direction="column" gap={{ base: 4, md: 6 }} pt={6}>
<ValidatorDescription />
<Flex
gap={{ base: 4, md: 6 }}
direction={{ base: "column", md: "row" }}
>
<VotingPowerOverview />
<UptimeSection onViewMore={onSelectPerformance} />
</Flex>
{!isMobile && (
<>
<Flex backgroundColor="gray.900" p={6} rounded={8} w="100%">
<RecentBlocksSection hasTitle />
</Flex>
{!move.enabled && (
<VotingPowerChart validatorAddress={validatorAddress} />
)}
</>
)}
{isMobile && !move.enabled && (
<BondedTokenChangeMobileCard
denom="OSMO"
onViewMore={onSelectBondedTokenChanges}
/>
)}
<ProposedBlocksTable
validatorAddress={validatorAddress}
onViewMore={onSelectPerformance}
/>
<VotedProposalsTable onViewMore={onSelectVotes} />
</Flex>
{/* TODO: change to conditions and remove line 72-74 */}
{/* Inactive */}
<Flex bg="teal.400" my={6}>
INACTIVE
return isActive && !isJailed ? (
<Flex direction="column" gap={{ base: 4, md: 6 }} pt={6}>
<ValidatorDescription details={details} />
<Flex gap={{ base: 4, md: 6 }} direction={{ base: "column", md: "row" }}>
<VotingPowerOverview />
<UptimeSection onViewMore={onSelectPerformance} />
</Flex>
{isMobile ? (
<BondedTokenChangeMobileCard
denom="OSMO"
onViewMore={onSelectBondedTokenChanges}
/>
) : (
<>
<Flex backgroundColor="gray.900" p={6} rounded={8} w="100%">
<RecentBlocksSection hasTitle />
</Flex>
<VotingPowerChart
validatorAddress={validatorAddress}
singleStakingDenom={singleStakingDenom}
assetInfos={assetInfos}
/>
</>
)}
<ProposedBlocksTable
validatorAddress={validatorAddress}
onViewMore={onSelectPerformance}
/>
<VotedProposalsTable onViewMore={onSelectVotes} />
</Flex>
) : (
<>
<Alert variant="error" gap={2} my={6}>
<CustomIcon name="alert-circle-solid" boxSize={4} color="error.main" />
<AlertDescription>
This validator is currently inactive. The information displayed
reflects the latest available data.
This validator is currently {isJailed ? "jailed" : "inactive"}. The
information displayed reflects the latest available data.
</AlertDescription>
</Alert>
<ValidatorDescription />
<ValidatorDescription details={details} />
<EmptyState
message="This validator has recently begun their duties. Let's extend our best wishes for their success in their role. 😊"
imageVariant="empty"
Expand Down
Loading

0 comments on commit 2de4564

Please sign in to comment.