Skip to content

Commit

Permalink
Merge pull request #602 from subquery/feat/new-project-detail
Browse files Browse the repository at this point in the history
feat(SQN-2038): new project detail & web app name
  • Loading branch information
HuberTRoy authored Nov 23, 2023
2 parents caecbc5 + 750174d commit b5c53f0
Show file tree
Hide file tree
Showing 23 changed files with 661 additions and 117 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
"@subql/contract-sdk": "0.16.2",
"@subql/network-clients": "^0.3.17",
"@subql/network-config": "0.3.17-2",
"@subql/network-query": "0.3.16-15",
"@subql/react-hooks": "0.3.16-23",
"@subql/network-query": "0.3.16-18",
"@subql/react-hooks": "0.3.16-26",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
Expand All @@ -37,7 +37,7 @@
"@web3-react/injected-connector": "^6.0.7",
"@web3-react/network-connector": "^6.1.9",
"ahooks": "^3.7.8",
"antd": "^5.8.4",
"antd": "^5.11.3",
"axios": "^1.4.0",
"bignumber.js": "^9.1.1",
"buffer": "^6.0.3",
Expand Down
4 changes: 2 additions & 2 deletions public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"short_name": "SubQuery Kepler Explorer",
"name": "SubQuery Kepler Explorer",
"icons": [
{
"src": "favicon.ico",
Expand Down
11 changes: 9 additions & 2 deletions src/components/Detail/Detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import * as React from 'react';
import { Typography } from '@subql/components';

import Copy from '../Copy';
import styles from './Details.module.css';
Expand All @@ -26,15 +27,21 @@ const Detail: React.FC<Props> = ({ label, value, href, className, canCopy, child
}

if (value) {
return <p className={styles.value}>{value}</p>;
return (
<Typography className={styles.value} variant="medium">
{value}
</Typography>
);
}

return children;
};

return (
<div className={[styles.detail, className].join(' ')}>
<span className="label">{label}</span>
<Typography type="secondary" variant="medium">
{label}
</Typography>
<div className={styles.valueCont}>
{renderValue()}
{canCopy && <Copy value={href ?? value} className={styles.copy} />}
Expand Down
1 change: 0 additions & 1 deletion src/components/Detail/Details.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
.value {
text-decoration: none;
color: var(--gray900);
font-size: 16px;
line-height: 24px;
letter-spacing: 0.3px;
font-weight: normal;
Expand Down
4 changes: 2 additions & 2 deletions src/components/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import * as React from 'react';
import { AiOutlineDown } from 'react-icons/ai';
import { BsChevronDown } from 'react-icons/bs';
import { Typography } from '@subql/components';
import { Dropdown as AntdDropdown, Menu } from 'antd';
import clsx from 'clsx';
Expand Down Expand Up @@ -48,7 +48,7 @@ export const Dropdown: React.FC<DropdownProps> = ({ menu, menuItem, dropdownCont
<AntdDropdown overlay={menuList} className={clsx(styles.hosted, 'flex-center', styleProps)}>
{typeof dropdownContent === 'string' || !dropdownContent ? (
<div>
{dropdownContent || menu[0]?.label} <AiOutlineDown className={styles.downIcon} />
{dropdownContent || menu[0]?.label} <BsChevronDown className={styles.downIcon} />
</div>
) : (
dropdownContent
Expand Down
1 change: 1 addition & 0 deletions src/components/Markdown/index.module.less
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.markdown {
color: var(--sq-gray700);
:global {
p {
margin: 1em 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
.lower {
display: flex;
flex-direction: row;
gap: 48px;
}

.image {
Expand All @@ -37,11 +38,11 @@
.titleVersion {
display: flex;
align-items: center;
margin-bottom: 8px;
}

.name {
align-self: flex-start;
padding-right: 16px;
}

.ownerIcon {
Expand All @@ -65,8 +66,10 @@
}

.dropdown {
padding: 6px;
border: 1px solid var(--gradient-to);
border-radius: 1rem;
color: var(--gradient-to);
margin-left: 16px;
padding: 10px 16px;
border: 1px solid var(--sq-gray300);
border-radius: 34px;
color: #000;
height: 38px;
}
14 changes: 10 additions & 4 deletions src/components/ProjectHeader/ProjectHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import UnsafeWarn from '@components/UnsafeWarn';
import { ProjectDetailsQuery } from '@hooks/useProjectFromQuery';
import { Address, Typography } from '@subql/components';
import dayjs from 'dayjs';

import { ProjectWithMetadata } from '../../models';
import Detail from '../Detail';
import { Dropdown } from '../Dropdown';
import IPFSImage from '../IPFSImage';
import styles from './ProjectHeader.module.css';
import styles from './ProjectHeader.module.less';

type Props = {
project: Required<ProjectWithMetadata>;
project: ProjectDetailsQuery;
versions?: Record<string, string>;
currentVersion?: string;
onChangeVersion?: (key: string) => void;
Expand All @@ -23,6 +24,9 @@ type Props = {
const ProjectHeader: React.FC<Props> = ({ project, versions, currentVersion, isUnsafeDeployment, onChangeVersion }) => {
const { t } = useTranslation();

const createdAtStr = React.useMemo(() => dayjs(project.createdTimestamp).fromNow(), [project]);
const updatedAtStr = React.useMemo(() => dayjs(project.updatedTimestamp).fromNow(), [project]);

const VersionDropdown = () => {
if (!versions) return <></>;

Expand Down Expand Up @@ -50,7 +54,7 @@ const ProjectHeader: React.FC<Props> = ({ project, versions, currentVersion, isU
<div className={styles.inner}>
<div className={styles.upper}>
<div className={styles.titleVersion}>
<Typography variant="h4" className={styles.name}>
<Typography variant="h4" className={styles.name} weight={600}>
{project.metadata.name}
</Typography>
{isUnsafeDeployment && <UnsafeWarn></UnsafeWarn>}
Expand All @@ -60,6 +64,8 @@ const ProjectHeader: React.FC<Props> = ({ project, versions, currentVersion, isU
</div>
<div className={styles.lower}>
{currentVersion && <Detail label={t('projectHeader.deploymentId')} value={currentVersion} canCopy={true} />}
<Detail label={t('projectOverview.updatedAt')} value={updatedAtStr} className={styles.column} />
<Detail label={t('projectOverview.createdAt')} value={createdAtStr} className={styles.column} />
</div>
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/components/ProjectOverview/ProjectOverview.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@

.linkContainer {
padding-bottom: 16px;
display: flex;
align-items: center;
}

.link {
Expand Down
114 changes: 87 additions & 27 deletions src/components/ProjectOverview/ProjectOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,118 @@

import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { BsGithub, BsGlobe } from 'react-icons/bs';
import Markdown from '@components/Markdown';
import moment from 'moment';
import NewCard from '@components/NewCard';
import { useRouteQuery } from '@hooks';
import { ProjectDetailsQuery } from '@hooks/useProjectFromQuery';
import { BalanceLayout } from '@pages/dashboard';
import { Typography } from '@subql/components';
import { formatSQT, useGetOfferCountByDeploymentIdLazyQuery } from '@subql/react-hooks';

import { ProjectMetadata } from '../../models';
import Detail from '../Detail';
import styles from './ProjectOverview.module.less';

type Props = {
project: ProjectDetailsQuery;
metadata: ProjectMetadata;
deploymentDescription?: string;
createdAt: Date;
updatedAt: Date;
};

const ExternalLink: React.FC<{ link?: string; icon: 'globe' | 'github' }> = ({ link, icon }) => {
return (
<div className={styles.linkContainer}>
<i className={`bi-${icon}`} role="img" aria-label={icon} />
<a className={styles.link} href={link} target="_blank" rel="noreferrer">
{link || 'N/A'}
</a>
{icon === 'github' ? (
<BsGithub style={{ color: 'var(--sq-blue600)', marginRight: 8 }}></BsGithub>
) : (
<BsGlobe style={{ color: 'var(--sq-blue600)', marginRight: 8 }}></BsGlobe>
)}
<Typography.Link href={link as string}>{link || 'N/A'}</Typography.Link>
</div>
);
};

const ProjectOverview: React.FC<Props> = ({ metadata, deploymentDescription, createdAt, updatedAt }) => {
const ProjectOverview: React.FC<Props> = ({ project, metadata, deploymentDescription }) => {
const { t } = useTranslation();
const createdAtStr = React.useMemo(() => moment(createdAt).utc(true).fromNow(), [createdAt]);
const updatedAtStr = React.useMemo(() => moment(updatedAt).utc(true).fromNow(), [updatedAt]);
const query = useRouteQuery();

const deploymentId = React.useMemo(() => {
return query.get('deploymentId') || project.currentDeployment;
}, [project, query]);

const [getOfferCounts, offerCounts] = useGetOfferCountByDeploymentIdLazyQuery({
variables: {
deploymentId,
},
defaultOptions: {
fetchPolicy: 'network-only',
},
});

React.useEffect(() => {
getOfferCounts({
variables: {
deploymentId,
},
});
}, [deploymentId]);

return (
<div className={styles.container}>
<div className={styles.column}>
<ExternalLink icon="globe" link={metadata.websiteUrl} />
<ExternalLink icon="github" link={metadata.codeUrl} />
<div className={styles.left}>
<Detail label={t('projectOverview.createdAt')} value={createdAtStr} className={styles.column} />
<Detail label={t('projectOverview.updatedAt')} value={updatedAtStr} className={styles.column} />
<div style={{ display: 'flex', flexDirection: 'column' }}>
<div style={{ width: 720 }}>
<Markdown>{metadata.description || 'N/A'}</Markdown>
</div>
<div className={styles.column} style={{ marginTop: 16 }}>
<ExternalLink icon="globe" link={metadata.websiteUrl} />
<ExternalLink icon="github" link={metadata.codeUrl} />
</div>
<div style={{ height: 1, width: '100%', background: 'var(--sq-gray300)', marginBottom: 16 }}></div>
<div className={styles.column}>
<Typography variant="medium" weight={600}>
{t('projectOverview.deploymentDescription')}
</Typography>
<div style={{ width: 670, marginTop: 8 }}>
<Markdown>{deploymentDescription || 'N/A'}</Markdown>
</div>
</div>
</div>

<div className={styles.column}>
<Detail label={'Project Description'}>
<div style={{ width: 670 }}>
<Markdown>{metadata.description || 'N/A'}</Markdown>
</div>
</Detail>
<Detail label={t('projectOverview.deploymentDescription')}>
<div style={{ width: 670 }}>
<Markdown>{deploymentDescription || 'N/A'}</Markdown>
<div style={{ marginLeft: 48, width: '100%' }}>
<NewCard
style={{ width: '100%' }}
title="Total Rewards"
titleExtra={BalanceLayout({
mainBalance: formatSQT(project.totalReward),
})}
>
<div className="col-flex">
<div className="flex" style={{ justifyContent: 'space-between' }}>
<Typography variant="small" type="secondary">
Total Indexers
</Typography>
<Typography variant="small">
{project.deployments.nodes.find((i) => i?.id === deploymentId)?.indexers.totalCount || 0}
</Typography>
</div>

<div className="flex" style={{ justifyContent: 'space-between', margin: '12px 0' }}>
<Typography variant="small" type="secondary">
Total Agreements
</Typography>
<Typography variant="small">
{project.deployments.nodes.find((i) => i?.id === deploymentId)?.serviceAgreements.totalCount || 0}
</Typography>
</div>

<div className="flex" style={{ justifyContent: 'space-between' }}>
<Typography variant="small" type="secondary">
Total Offers
</Typography>
<Typography variant="small">{offerCounts.data?.offers?.totalCount || 0}</Typography>
</div>
</div>
</Detail>
</NewCard>
</div>
</div>
);
Expand Down
40 changes: 0 additions & 40 deletions src/components/TabButton/TabButton.module.css

This file was deleted.

Loading

0 comments on commit b5c53f0

Please sign in to comment.