diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx
index 5cdf84d93..2c93dc564 100644
--- a/src/components/Header/Header.tsx
+++ b/src/components/Header/Header.tsx
@@ -37,17 +37,6 @@ export interface AppNavigation {
export const Header: React.FC = () => {
const { address: account } = useAccount();
const navigate = useNavigate();
- const calEntryLinks = React.useMemo(() => {
- return entryLinks.map((entry) => {
- if (entry.key === 'explorer') {
- return {
- ...entry,
- dropdown: undefined,
- };
- }
- return entry;
- });
- }, []);
return (
@@ -55,7 +44,7 @@ export const Header: React.FC = () => {
navigate={(link) => {
navigate(link);
}}
- appNavigation={calEntryLinks}
+ appNavigation={entryLinks}
dropdownLinks={{ label: 'Kepler', links: externalAppLinks }}
rightElement={
<>
diff --git a/src/components/IndexerDetails/IndexerDetails.module.less b/src/components/IndexerDetails/IndexerDetails.module.less
index e9d9f73a9..a4fd443c1 100644
--- a/src/components/IndexerDetails/IndexerDetails.module.less
+++ b/src/components/IndexerDetails/IndexerDetails.module.less
@@ -170,6 +170,8 @@
color: #fff;
font-size: 18px;
margin-bottom: 8px;
+ display: flex;
+ align-items: center;
}
&LimitInfo {
diff --git a/src/components/IndexerDetails/IndexerDetails.tsx b/src/components/IndexerDetails/IndexerDetails.tsx
index 87ce54705..5fc6683af 100644
--- a/src/components/IndexerDetails/IndexerDetails.tsx
+++ b/src/components/IndexerDetails/IndexerDetails.tsx
@@ -4,6 +4,7 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { EmptyList } from '@components/EmptyList';
+import { ProjectDetailsQuery } from '@hooks/useProjectFromQuery';
import { Spinner, TableTitle, Typography } from '@subql/components';
import { ServiceStatus } from '@subql/network-query';
import { renderAsync, useGetDeploymentIndexersLazyQuery, useGetIndexerDeploymentLazyQuery } from '@subql/react-hooks';
@@ -16,6 +17,7 @@ import Row from './Row';
type Props = {
deploymentId: string | undefined;
+ project: ProjectDetailsQuery;
};
const NoIndexers: React.FC = () => {
@@ -31,7 +33,7 @@ const NoIndexers: React.FC = () => {
);
};
-const IndexerDetails: React.FC
= ({ deploymentId }) => {
+const IndexerDetails: React.FC = ({ deploymentId, project }) => {
const { t } = useTranslation();
const [loadIndexersLazy, asyncIndexers] = useGetDeploymentIndexersLazyQuery();
@@ -156,7 +158,7 @@ const IndexerDetails: React.FC = ({ deploymentId }) => {
.filter(notEmpty)
.sort((indexer) => (indexer.status === ServiceStatus.READY ? -1 : 1))
.map((indexer) => (
-
+
))}
>
diff --git a/src/components/IndexerDetails/Row.tsx b/src/components/IndexerDetails/Row.tsx
index 1ed089111..c3cbf24ff 100644
--- a/src/components/IndexerDetails/Row.tsx
+++ b/src/components/IndexerDetails/Row.tsx
@@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next';
import { BsChevronDown, BsChevronUp, BsInfoSquare } from 'react-icons/bs';
import { useNavigate } from 'react-router';
import { LazyQueryResult } from '@apollo/client';
+import RpcPlayground from '@components/RpcPlayground/RpcPlayground';
import { WalletRoute } from '@components/WalletRoute';
import { useIsLogin } from '@hooks/useIsLogin';
import { useRequestServiceAgreementToken } from '@hooks/useRequestServiceAgreementToken';
@@ -14,6 +15,7 @@ import { GraphiQL } from '@subql/components/dist/common/GraphiQL';
import {
GetDeploymentIndexersQuery,
PlansNodeFieldsFragment as Plan,
+ ProjectType,
ServiceStatus as DeploymentStatus,
} from '@subql/network-query';
import { useGetDeploymentPlansLazyQuery } from '@subql/react-hooks';
@@ -25,6 +27,7 @@ import clsx from 'clsx';
import { t } from 'i18next';
import { useAccount } from 'wagmi';
+import RpcPlaygroundIcon from 'src/images/rpcPlayground';
import { useWeb3Store } from 'src/stores';
import { useProjectStore } from 'src/stores/project';
@@ -77,7 +80,8 @@ export interface QueryLimit {
const ConnectedRow: React.FC<{
indexer: ExcludeNull
['nodes'][number]>;
deploymentId?: string;
-}> = ({ indexer, deploymentId }) => {
+ type: ProjectType;
+}> = ({ indexer, deploymentId, type }) => {
const { t } = useTranslation();
const { address: account } = useAccount();
const navigate = useNavigate();
@@ -175,7 +179,6 @@ const ConnectedRow: React.FC<{
>
),
},
-
{
width: '13%',
render: () => {
@@ -211,7 +214,16 @@ const ConnectedRow: React.FC<{
setShowReqTokenConfirmModal(true);
}}
>
-
+ {type === ProjectType.SUBQUERY ? (
+
+ ) : (
+
+ )}
Playground
);
@@ -332,7 +344,13 @@ const ConnectedRow: React.FC<{
>
{t('explorer.flexPlans.requestToken')}}
+ element={
+
+ {t('explorer.flexPlans.requestToken', {
+ type: type === ProjectType.RPC ? 'JSON' : 'Graphql',
+ })}
+
+ }
>
@@ -344,7 +362,11 @@ const ConnectedRow: React.FC<{
>
-
+ {type === ProjectType.SUBQUERY ? (
+
+ ) : (
+
+ )}
{t('myFlexPlans.playground')}
@@ -361,7 +383,10 @@ const ConnectedRow: React.FC<{
- {queryUrl && trailToken && }
+ {type === ProjectType.SUBQUERY && queryUrl && trailToken && (
+
+ )}
+ {type === ProjectType.RPC && }
>
);
diff --git a/src/components/ProjectHeader/ProjectHeader.tsx b/src/components/ProjectHeader/ProjectHeader.tsx
index 25cc62b09..f6ee18363 100644
--- a/src/components/ProjectHeader/ProjectHeader.tsx
+++ b/src/components/ProjectHeader/ProjectHeader.tsx
@@ -71,9 +71,10 @@ const ProjectHeader: React.FC = ({
{isUnsafeDeployment && }
-
+ {/* TODO: finish this */}
+ {/*
Get RPC Endpoint
-
+ */}
diff --git a/src/components/RpcPlayground/RpcPlayground.tsx b/src/components/RpcPlayground/RpcPlayground.tsx
new file mode 100644
index 000000000..c07eebfba
--- /dev/null
+++ b/src/components/RpcPlayground/RpcPlayground.tsx
@@ -0,0 +1,88 @@
+// Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
+// SPDX-License-Identifier: Apache-2.0
+
+import React, { FC, useMemo, useState } from 'react';
+import { Typography } from '@subql/components';
+import { getAuthReqHeader } from '@utils';
+import { Button, Input } from 'antd';
+import { fetchJson } from 'ethers/lib/utils';
+
+import styles from './index.module.less';
+
+interface IProps {
+ url?: string;
+ trailToken: string;
+}
+
+const RpcPlayground: FC = ({ url, trailToken }) => {
+ const [val, setVal] = useState('');
+ const [loading, setLoading] = useState(false);
+ const enteredRows = useMemo(() => {
+ return val.split('\n').length;
+ }, [val]);
+
+ const [responseData, setResponseData] = useState('');
+
+ const fetchRpc = async () => {
+ if (!url) return;
+ try {
+ setLoading(true);
+ const res = await fetchJson(
+ {
+ url,
+ headers: {
+ ...getAuthReqHeader(trailToken),
+ },
+ },
+ val,
+ );
+
+ setResponseData(JSON.stringify(res));
+ } catch (e: any) {
+ setResponseData(`${e.toString()}`);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+
+
+ Request
+
+ {
+ setVal(e.target.value);
+ }}
+ placeholder="JSON RPC playground is a simple tool to help you test queries, click to enter you requests."
+ >
+
+ {
+ fetchRpc();
+ }}
+ >
+ Send Request
+
+
+
+
+
+ Response
+
+
+ {responseData}
+
+
+
+ );
+};
+export default RpcPlayground;
diff --git a/src/components/RpcPlayground/index.module.less b/src/components/RpcPlayground/index.module.less
new file mode 100644
index 000000000..28001d4ab
--- /dev/null
+++ b/src/components/RpcPlayground/index.module.less
@@ -0,0 +1,37 @@
+.rpcPlayground {
+ display: flex;
+ padding: 16px;
+ border-radius: 0px 0px 16px 16px;
+ background: #2A3546;
+
+ &Editor {
+ flex: 1;
+ padding: 16px;
+ background: #1F2A3B;
+ border-radius: 10px;
+ position: relative;
+
+ :global {
+ .ant-input {
+ background: #1F2A3B;
+ border: 1px solid #1F2A3B;
+ color: var(--sq-gray500);
+ padding: 0;
+ font-family: var(--sq-font-family);
+ &:focus {
+ box-shadow: none;
+ }
+
+ &::placeholder {
+ color: var(--sq-gary500);
+ }
+ }
+ }
+ }
+
+ &Response {
+ flex: 1;
+ padding: 16px;
+
+ }
+}
\ No newline at end of file
diff --git a/src/hooks/useProjectList.module.less b/src/hooks/useProjectList.module.less
index 4c8539db9..0e4b7c119 100644
--- a/src/hooks/useProjectList.module.less
+++ b/src/hooks/useProjectList.module.less
@@ -8,7 +8,7 @@
.typeFilter {
display: flex;
- justify-content: center;
+ // justify-content: center;
margin-bottom: 40px;
:global {
diff --git a/src/hooks/useProjectList.tsx b/src/hooks/useProjectList.tsx
index 4accda27b..c1e38b08d 100644
--- a/src/hooks/useProjectList.tsx
+++ b/src/hooks/useProjectList.tsx
@@ -5,12 +5,13 @@ import React, { useMemo, useState } from 'react';
import SearchOutlined from '@ant-design/icons/SearchOutlined';
import { ProjectCard } from '@components';
import { useProjectMetadata } from '@containers';
+import { PublishNewProjectModal } from '@pages/studio/Home/Home';
import { SubqlCheckbox } from '@subql/components';
import { ProjectFieldsFragment, ProjectsOrderBy, ProjectType } from '@subql/network-query';
import { useAsyncMemo, useGetProjectLazyQuery, useGetProjectsLazyQuery } from '@subql/react-hooks';
import { categoriesOptions, notEmpty, rpcCategoriesOptions } from '@utils';
import { useInfiniteScroll, useMount } from 'ahooks';
-import { Input, Radio, Skeleton, Typography } from 'antd';
+import { Button, Input, Radio, Skeleton, Typography } from 'antd';
import { useGetDeploymentManifest } from './useGetDeploymentManifest';
import { useLocalProjects } from './useLocalProjects';
@@ -63,6 +64,7 @@ export const useProjectList = (props: UseProjectListProps = {}) => {
// assum there at lease have 11 projects
const [total, setTotal] = React.useState(10);
const [inSearchMode, setInSearchMode] = React.useState(false);
+ const [showPublishModal, setShowPublishModal] = React.useState(false);
const { getProjectBySearch } = useLocalProjects();
@@ -236,6 +238,23 @@ export const useProjectList = (props: UseProjectListProps = {}) => {
buttonStyle="solid"
size="large"
/>
+
+ {
+ setShowPublishModal(true);
+ }}
+ >
+ Publish New Project
+
+ {
+ setShowPublishModal(val);
+ }}
+ >
diff --git a/src/i18n/en/explorer.ts b/src/i18n/en/explorer.ts
index c8110ca03..da83cb1ba 100644
--- a/src/i18n/en/explorer.ts
+++ b/src/i18n/en/explorer.ts
@@ -105,7 +105,7 @@ const translation = {
indexer: 'indexer',
validityPeriod: 'Validity Period',
non: 'There are no flex plans for this project yet.',
- requestToken: 'To start testing your queries in the GraphQL playground, simply request a trial token.',
+ requestToken: 'To start testing your queries in the {{type}} playground, simply request a trial token.',
remainLimit: 'Remain requests limit: {{limit}}',
expireTime: 'Token expires in {{time}}',
},
diff --git a/src/images/rpcPlayground.tsx b/src/images/rpcPlayground.tsx
new file mode 100644
index 000000000..934c63f29
--- /dev/null
+++ b/src/images/rpcPlayground.tsx
@@ -0,0 +1,60 @@
+// Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
+// SPDX-License-Identifier: Apache-2.0
+
+import { FC } from 'react';
+
+export type Icon = {
+ color?: string;
+ width?: number;
+ height?: number;
+ style?: React.CSSProperties;
+};
+
+const RpcPlaygroundIcon: FC
= ({ color = '#fff', width = 18, height = 18, style }) => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default RpcPlaygroundIcon;
diff --git a/src/pages/delegator/AllIndexers/AllIndexers.tsx b/src/pages/delegator/AllIndexers/AllIndexers.tsx
index b3ebf1cb5..50f1cac06 100644
--- a/src/pages/delegator/AllIndexers/AllIndexers.tsx
+++ b/src/pages/delegator/AllIndexers/AllIndexers.tsx
@@ -4,11 +4,12 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { EmptyList, WalletRoute } from '@components';
+import RpcError from '@components/RpcError';
import { useEra } from '@hooks';
import { Spinner, Typography } from '@subql/components';
import { useGetIndexersQuery } from '@subql/react-hooks';
-import { getUseQueryFetchMore, mapAsync, mergeAsync, notEmpty, renderAsync } from '../../../utils';
+import { getUseQueryFetchMore, isRPCError, mapAsync, mergeAsync, notEmpty, renderAsync } from '../../../utils';
import { IndexerList } from './IndexerList/IndexerList';
export const AllIndexers: React.FC = () => {
@@ -35,7 +36,13 @@ export const AllIndexers: React.FC = () => {
),
{
loading: () => ,
- error: (error) => {`Error: Failed to get Indexers: ${error.message}`} ,
+ error: (error) => {
+ if (isRPCError(error)) {
+ return ;
+ }
+
+ return {`Error: Failed to get Indexers: ${error.message}`} ;
+ },
data: (data) => {
if (!data || data?.totalCount === 0) {
;
diff --git a/src/pages/explorer/Home/Home.module.css b/src/pages/explorer/Home/Home.module.css
index bf9b29275..18448c381 100644
--- a/src/pages/explorer/Home/Home.module.css
+++ b/src/pages/explorer/Home/Home.module.css
@@ -7,7 +7,7 @@
.header {
display: flex;
flex-direction: column;
- margin-bottom: 72px;
+ margin-bottom: 18px;
}
.headerTitle {
diff --git a/src/pages/explorer/Home/Home.tsx b/src/pages/explorer/Home/Home.tsx
index 0325152bb..b1a6b700c 100644
--- a/src/pages/explorer/Home/Home.tsx
+++ b/src/pages/explorer/Home/Home.tsx
@@ -5,9 +5,7 @@ import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router';
import { useProjectList } from '@hooks/useProjectList';
-import { PublishNewProjectModal } from '@pages/studio/Home/Home';
import { Typography } from '@subql/components';
-import { Button } from 'antd';
import { ROUTES } from '../../../utils';
import styles from './Home.module.css';
@@ -17,7 +15,6 @@ const { PROJECT_NAV } = ROUTES;
// TODO move to components
export const Header: React.FC = () => {
const { t } = useTranslation();
- const [showPublishModal, setShowPublishModal] = React.useState(false);
return (
@@ -26,23 +23,7 @@ export const Header: React.FC = () => {
{t('explorer.home.headerDesc')}
- {
- setShowPublishModal(true);
- }}
- >
- Publish New Project
-
- {
- setShowPublishModal(val);
- }}
- >
);
};
diff --git a/src/pages/explorer/Project/Project.tsx b/src/pages/explorer/Project/Project.tsx
index 56d96d521..bcc507515 100644
--- a/src/pages/explorer/Project/Project.tsx
+++ b/src/pages/explorer/Project/Project.tsx
@@ -45,7 +45,7 @@ const ProjectInner: React.FC = () => {
{ link: `${OVERVIEW}${location.search}`, label: t('explorer.project.tab1') },
{
link: `${INDEXERS}${location.search}`,
- label: asyncProject.data?.type === ProjectType.RPC ? 'RPC Endpoints' : t('explorer.project.tab2'),
+ label: asyncProject.data?.type === ProjectType.RPC ? 'RPC Providers' : t('explorer.project.tab2'),
},
{ link: `${SERVICE_AGREEMENTS}${location.search}`, label: t('explorer.project.tab3') },
];
@@ -158,7 +158,10 @@ const ProjectInner: React.FC = () => {
/>
}
/>
-
} />
+ }
+ />
{
},
});
- const [showCreateModal, setShowCreateModal] = React.useState(false);
- const enableCreateModal = () => setShowCreateModal(true);
-
return (
My Projects
-
- Publish New Project
-
-
{
- setShowCreateModal(val);
- }}
- />
-
{listsWithSearch}
);