Feat/707 link to market proposal (#1222)
* feat: link to market proposal (707) * feat: link to market proposal (707) * removed a line * removed label which made edd and barney sad
This commit is contained in:
parent
47554973c5
commit
e674efdb14
@ -9,6 +9,7 @@ import Routes from '../../../routes';
|
||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Links } from '../../../../config';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
interface ProposalsListProps {
|
||||
proposals: Proposals_proposals[];
|
||||
@ -65,14 +66,9 @@ export const ProposalsList = ({ proposals }: ProposalsListProps) => {
|
||||
{t(
|
||||
`The Vega network is governed by the community. View active proposals, vote on them or propose changes to the network.`
|
||||
)}{' '}
|
||||
<a
|
||||
href={Links.GOVERNANCE_PAGE}
|
||||
className="underline text-white"
|
||||
target="_blank"
|
||||
rel="nofollow noreferrer"
|
||||
>
|
||||
<ExternalLink href={Links.GOVERNANCE_PAGE} className="text-white">
|
||||
{t(`Find out more about Vega governance`)}
|
||||
</a>
|
||||
</ExternalLink>
|
||||
</p>
|
||||
</div>
|
||||
{proposals.length > 0 && (
|
||||
|
@ -20,6 +20,15 @@ export const generateMarketInfoQuery = (
|
||||
positionDecimalPlaces: 0,
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
proposal: {
|
||||
__typename: 'Proposal',
|
||||
id: 'market-0',
|
||||
rationale: {
|
||||
__typename: 'ProposalRationale',
|
||||
title: 'ETHBTC',
|
||||
description: '',
|
||||
},
|
||||
},
|
||||
accounts: [
|
||||
{
|
||||
type: AccountType.ACCOUNT_TYPE_INSURANCE,
|
||||
|
@ -6,4 +6,5 @@ NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\"}
|
||||
NX_USE_ENV_OVERRIDES=1
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789/api/v1
|
@ -6,3 +6,4 @@ NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\"}
|
||||
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
|
||||
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
|
@ -6,3 +6,4 @@ NX_VEGA_NETWORKS='{\"MAINNET\":\"https://alpha.console.vega.xyz\"}'
|
||||
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
|
||||
NX_VEGA_TOKEN_URL=https://token.vega.xyz
|
@ -6,3 +6,4 @@ NX_VEGA_NETWORKS='{\"MAINNET\":\"https://alpha.console.vega.xyz\"}'
|
||||
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://staging3.explorer.vega.xyz
|
||||
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
|
@ -5,3 +5,4 @@ NX_VEGA_NETWORKS='{\"MAINNET\":\"https://alpha.console.vega.xyz\"}'
|
||||
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
|
@ -9,6 +9,34 @@ import { Interval, MarketState, AccountType, MarketTradingMode, AuctionTrigger }
|
||||
// GraphQL query operation: MarketInfoQuery
|
||||
// ====================================================
|
||||
|
||||
export interface MarketInfoQuery_market_proposal_rationale {
|
||||
__typename: "ProposalRationale";
|
||||
/**
|
||||
* Title to be used to give a short description of the proposal in lists.
|
||||
* This is to be between 0 and 100 unicode characters.
|
||||
* This is mandatory for all proposals.
|
||||
*/
|
||||
title: string;
|
||||
/**
|
||||
* Description to show a short title / something in case the link goes offline.
|
||||
* This is to be between 0 and 20k unicode characters.
|
||||
* This is mandatory for all proposals.
|
||||
*/
|
||||
description: string;
|
||||
}
|
||||
|
||||
export interface MarketInfoQuery_market_proposal {
|
||||
__typename: "Proposal";
|
||||
/**
|
||||
* Proposal ID that is filled by Vega once proposal reaches the network
|
||||
*/
|
||||
id: string | null;
|
||||
/**
|
||||
* Rationale behind the proposal
|
||||
*/
|
||||
rationale: MarketInfoQuery_market_proposal_rationale;
|
||||
}
|
||||
|
||||
export interface MarketInfoQuery_market_accounts_asset {
|
||||
__typename: "Asset";
|
||||
/**
|
||||
@ -451,6 +479,10 @@ export interface MarketInfoQuery_market {
|
||||
* Current state of the market
|
||||
*/
|
||||
state: MarketState;
|
||||
/**
|
||||
* The proposal that initiated this market
|
||||
*/
|
||||
proposal: MarketInfoQuery_market_proposal | null;
|
||||
/**
|
||||
* Get account for a party or market
|
||||
*/
|
||||
|
@ -8,6 +8,13 @@ export const MARKET_INFO_QUERY = gql`
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
state
|
||||
proposal {
|
||||
id
|
||||
rationale {
|
||||
title
|
||||
description
|
||||
}
|
||||
}
|
||||
accounts {
|
||||
type
|
||||
asset {
|
||||
@ -16,13 +23,6 @@ export const MARKET_INFO_QUERY = gql`
|
||||
balance
|
||||
}
|
||||
tradingMode
|
||||
accounts {
|
||||
type
|
||||
asset {
|
||||
id
|
||||
}
|
||||
balance
|
||||
}
|
||||
fees {
|
||||
factors {
|
||||
makerFee
|
||||
@ -44,13 +44,6 @@ export const MARKET_INFO_QUERY = gql`
|
||||
short
|
||||
long
|
||||
}
|
||||
accounts {
|
||||
type
|
||||
asset {
|
||||
id
|
||||
}
|
||||
balance
|
||||
}
|
||||
data {
|
||||
market {
|
||||
id
|
||||
|
@ -26,6 +26,14 @@ import { useQuery } from '@apollo/client';
|
||||
import { totalFees } from '@vegaprotocol/market-list';
|
||||
import { AccountType, Interval } from '@vegaprotocol/types';
|
||||
import { MARKET_INFO_QUERY } from './info-market-query';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
import { generatePath } from 'react-router-dom';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
|
||||
const Links = {
|
||||
PROPOSAL_PAGE: ':tokenUrl/governance/:proposalId',
|
||||
};
|
||||
|
||||
export interface InfoProps {
|
||||
market: MarketInfoQuery_market;
|
||||
@ -68,7 +76,8 @@ export const MarketInfoContainer = ({ marketId }: MarketInfoContainerProps) => {
|
||||
};
|
||||
|
||||
export const Info = ({ market }: InfoProps) => {
|
||||
const headerClassName = 'uppercase text-lg mb-4';
|
||||
const { VEGA_TOKEN_URL } = useEnvironment();
|
||||
const headerClassName = 'uppercase text-lg';
|
||||
const dayVolume = calcCandleVolume(market);
|
||||
const marketDataPanels = [
|
||||
{
|
||||
@ -272,16 +281,45 @@ export const Info = ({ market }: InfoProps) => {
|
||||
},
|
||||
];
|
||||
|
||||
const marketGovPanels = [
|
||||
{
|
||||
title: t('Proposal'),
|
||||
content: (
|
||||
<p>
|
||||
<ExternalLink
|
||||
href={generatePath(Links.PROPOSAL_PAGE, {
|
||||
tokenUrl: VEGA_TOKEN_URL,
|
||||
proposalId: market.proposal?.id || '',
|
||||
})}
|
||||
title={
|
||||
market.proposal?.rationale.title ||
|
||||
market.proposal?.rationale.description ||
|
||||
''
|
||||
}
|
||||
>
|
||||
{t('View governance proposal')}
|
||||
</ExternalLink>
|
||||
</p>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<div className="mb-4">
|
||||
<p className={headerClassName}>{t('Market data')}</p>
|
||||
<Accordion panels={marketDataPanels} />
|
||||
</div>
|
||||
<div>
|
||||
<div className="mb-4">
|
||||
<p className={headerClassName}>{t('Market specification')}</p>
|
||||
<Accordion panels={marketSpecPanels} />
|
||||
</div>
|
||||
{VEGA_TOKEN_URL && market.proposal?.id && (
|
||||
<div>
|
||||
<p className={headerClassName}>{t('Market governance')}</p>
|
||||
<Accordion panels={marketGovPanels} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -70,6 +70,8 @@ const getBundledEnvironmentValue = (key: EnvKey) => {
|
||||
return process.env['NX_VEGA_EXPLORER_URL'];
|
||||
case 'VEGA_WALLET_URL':
|
||||
return process.env['NX_VEGA_WALLET_URL'];
|
||||
case 'VEGA_TOKEN_URL':
|
||||
return process.env['NX_VEGA_TOKEN_URL'];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@ const schemaObject = {
|
||||
GITHUB_FEEDBACK_URL: z.optional(z.string()),
|
||||
VEGA_ENV: z.nativeEnum(Networks),
|
||||
VEGA_EXPLORER_URL: z.optional(z.string()),
|
||||
VEGA_TOKEN_URL: z.optional(z.string()),
|
||||
VEGA_NETWORKS: z
|
||||
.object(
|
||||
Object.keys(Networks).reduce(
|
||||
|
@ -7,7 +7,7 @@ export type { IconName } from '@blueprintjs/icons';
|
||||
export interface IconProps {
|
||||
name: IconName;
|
||||
className?: string;
|
||||
size?: 4 | 6 | 8 | 10 | 12 | 14 | 16;
|
||||
size?: 2 | 3 | 4 | 6 | 8 | 10 | 12 | 14 | 16;
|
||||
ariaLabel?: string;
|
||||
}
|
||||
|
||||
@ -21,6 +21,8 @@ export const Icon = ({ size = 4, name, className, ariaLabel }: IconProps) => {
|
||||
// Cant just concatenate as TW wont pick up that the class is being used
|
||||
// so below syntax is required
|
||||
{
|
||||
'w-2 h-2': size === 2,
|
||||
'w-3 h-3': size === 3,
|
||||
'w-4 h-4': size === 4,
|
||||
'w-6 h-6': size === 6,
|
||||
'w-8 h-8': size === 8,
|
||||
|
@ -1 +1 @@
|
||||
export { Link } from './link';
|
||||
export * from './link';
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { Link } from '.';
|
||||
import { ExternalLink, Link } from '.';
|
||||
|
||||
it('renders a link with a text', () => {
|
||||
describe('Link', () => {
|
||||
it('renders a link with a text', () => {
|
||||
render(
|
||||
<Link href="127.0.0.1" title="Link title">
|
||||
Link text
|
||||
@ -15,9 +16,9 @@ it('renders a link with a text', () => {
|
||||
expect(link).toHaveAttribute('title', 'Link title');
|
||||
expect(link).toHaveClass('cursor-pointer');
|
||||
expect(link).toHaveClass('underline');
|
||||
});
|
||||
});
|
||||
|
||||
it('renders a link with children elements', () => {
|
||||
it('renders a link with children elements', () => {
|
||||
render(
|
||||
<Link href="127.0.0.1" title="Link title">
|
||||
<span>Link text</span>
|
||||
@ -31,4 +32,31 @@ it('renders a link with children elements', () => {
|
||||
expect(link).toHaveAttribute('title', 'Link title');
|
||||
expect(link).toHaveClass('cursor-pointer');
|
||||
expect(link).not.toHaveClass('underline');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ExternalLink', () => {
|
||||
it('should have an icon indicating that it is an external link', () => {
|
||||
render(<ExternalLink href="https://vega.xyz/">Go to Vega</ExternalLink>);
|
||||
const link = screen.getByTestId('external-link');
|
||||
expect(link.children.length).toEqual(2);
|
||||
expect(link.children[1].tagName.toUpperCase()).toEqual('SVG');
|
||||
});
|
||||
|
||||
it('should have an underlined text part', () => {
|
||||
render(<ExternalLink href="https://vega.xyz/">Go to Vega</ExternalLink>);
|
||||
const link = screen.getByTestId('external-link');
|
||||
expect(link.children[0]).toHaveClass('underline');
|
||||
});
|
||||
|
||||
it('should not have an icon or underlined text if wrapping an element', () => {
|
||||
render(
|
||||
<ExternalLink href="https://vega.xyz/">
|
||||
<div className="inner">inner element</div>
|
||||
</ExternalLink>
|
||||
);
|
||||
const link = screen.getByTestId('external-link');
|
||||
expect(link.children.length).toEqual(1);
|
||||
expect(link.children[0]).toHaveClass('inner');
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import classNames from 'classnames';
|
||||
import type { ReactNode, AnchorHTMLAttributes } from 'react';
|
||||
import { Icon } from '../icon';
|
||||
|
||||
type LinkProps = AnchorHTMLAttributes<HTMLAnchorElement> & {
|
||||
children?: ReactNode;
|
||||
@ -27,5 +29,27 @@ export const Link = ({ className, children, ...props }: LinkProps) => {
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
Link.displayName = 'Link';
|
||||
|
||||
export const ExternalLink = ({ children, className, ...props }: LinkProps) => (
|
||||
<Link
|
||||
className={classNames(className, 'inline-flex items-baseline')}
|
||||
{...props}
|
||||
target="_blank"
|
||||
data-testid="external-link"
|
||||
>
|
||||
{typeof children === 'string' ? (
|
||||
<>
|
||||
<span
|
||||
className={classNames({ underline: typeof children === 'string' })}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
<Icon size={3} name={IconNames.SHARE} className="ml-1" />
|
||||
</>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</Link>
|
||||
);
|
||||
ExternalLink.displayName = 'ExternalLink';
|
||||
|
Loading…
Reference in New Issue
Block a user