Merge branch 'develop' into feature/sc-838/ui-finish-indexed-nfa-view-after-design-changes
This commit is contained in:
commit
65e7ec9429
|
|
@ -38,7 +38,7 @@ query getLatestNFAs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query getNFA($id: ID!) {
|
query getNFADetail($id: ID!) {
|
||||||
token(id: $id) {
|
token(id: $id) {
|
||||||
tokenId
|
tokenId
|
||||||
owner {
|
owner {
|
||||||
|
|
@ -50,6 +50,33 @@ query getNFA($id: ID!) {
|
||||||
externalURL
|
externalURL
|
||||||
logo
|
logo
|
||||||
color
|
color
|
||||||
|
createdAt
|
||||||
|
accessPoints {
|
||||||
|
createdAt
|
||||||
|
contentVerified
|
||||||
|
owner {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
id
|
||||||
|
}
|
||||||
|
verified
|
||||||
|
verifier {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
gitRepository {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query getNFA($id: ID!) {
|
||||||
|
token(id: $id) {
|
||||||
|
tokenId
|
||||||
|
name
|
||||||
|
ENS
|
||||||
|
externalURL
|
||||||
|
logo
|
||||||
|
color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,3 +10,45 @@ export const getRepoAndCommit = (url: string): object => {
|
||||||
export const contractAddress = (address: string): string => {
|
export const contractAddress = (address: string): string => {
|
||||||
return `${address.slice(0, 6)}...${address.slice(-4)}`;
|
return `${address.slice(0, 6)}...${address.slice(-4)}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getRepositoryFromURL = (url: string): string => {
|
||||||
|
const urlSplitted = url.split('/');
|
||||||
|
return `${urlSplitted[3]}/${urlSplitted[4]}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getDate = (date: number): string => {
|
||||||
|
return new Date(date * 1000).toLocaleDateString();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param date date in tiemstamp format
|
||||||
|
* @returns time since date
|
||||||
|
*/
|
||||||
|
export const getTimeSince = (date: number): string => {
|
||||||
|
const now = new Date().getTime(); //in timestamp format
|
||||||
|
|
||||||
|
const milliseconds = now - date * 1000;
|
||||||
|
const seconds = milliseconds / 1000;
|
||||||
|
const minutes = Math.round((seconds / 60) % 60);
|
||||||
|
const days = Math.round(seconds / (60 * 60 * 24));
|
||||||
|
const hours = Math.round(minutes % 60);
|
||||||
|
const months = Math.round(days / 30.5);
|
||||||
|
const years = Math.round(months / 12);
|
||||||
|
|
||||||
|
if (years > 0) {
|
||||||
|
return `${years} year${years > 1 ? 's' : ''} ago`;
|
||||||
|
}
|
||||||
|
if (months > 0) {
|
||||||
|
return `${months} month${months > 1 ? 's' : ''} ago`;
|
||||||
|
}
|
||||||
|
if (days > 0) {
|
||||||
|
return `${days} day${days > 1 ? 's' : ''} ago`;
|
||||||
|
}
|
||||||
|
if (hours > 0) {
|
||||||
|
return `${hours} hour${hours > 1 ? 's' : ''} ago`;
|
||||||
|
}
|
||||||
|
if (minutes > 0) {
|
||||||
|
return `${minutes} min ago`;
|
||||||
|
}
|
||||||
|
return `${Math.round(seconds)} sec ago}`;
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -70,8 +70,8 @@ export const CreateAccessPointFormBody: React.FC = () => {
|
||||||
},
|
},
|
||||||
onCompleted(data) {
|
onCompleted(data) {
|
||||||
if (data.token && id) {
|
if (data.token && id) {
|
||||||
const { name, tokenId, logo, color, externalURL: domain } = data.token;
|
const { name, tokenId, logo, color, externalURL } = data.token;
|
||||||
setNfa({ name, tokenId, logo, color, domain });
|
setNfa({ name, tokenId, logo, color, externalURL });
|
||||||
} else {
|
} else {
|
||||||
AppLog.errorToast("We couldn't find the NFA you are looking for");
|
AppLog.errorToast("We couldn't find the NFA you are looking for");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,15 @@
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import { Token } from '@/graphclient';
|
||||||
import { EthereumHooks } from '@/integrations';
|
import { EthereumHooks } from '@/integrations';
|
||||||
import { useFleekERC721Billing } from '@/store';
|
import { useFleekERC721Billing } from '@/store';
|
||||||
import { AppLog, createContext } from '@/utils';
|
import { AppLog, createContext } from '@/utils';
|
||||||
|
|
||||||
export type NFA = {
|
export type NFA = Pick<
|
||||||
tokenId: string;
|
Token,
|
||||||
name: string;
|
'tokenId' | 'name' | 'logo' | 'color' | 'externalURL'
|
||||||
logo: string;
|
>;
|
||||||
color: number;
|
|
||||||
domain: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AccessPointContext = {
|
export type AccessPointContext = {
|
||||||
billing: string | undefined;
|
billing: string | undefined;
|
||||||
|
|
@ -43,7 +41,7 @@ export abstract class CreateAccessPoint {
|
||||||
name: '',
|
name: '',
|
||||||
logo: '',
|
logo: '',
|
||||||
color: 0,
|
color: 0,
|
||||||
domain: '',
|
externalURL: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const value = {
|
const value = {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,15 @@ import React, { useState } from 'react';
|
||||||
import Rectangle1 from '@/assets/Rectangle-199.png';
|
import Rectangle1 from '@/assets/Rectangle-199.png';
|
||||||
import Rectangle2 from '@/assets/Rectangle-200.png';
|
import Rectangle2 from '@/assets/Rectangle-200.png';
|
||||||
import Rectangle3 from '@/assets/Rectangle-201.png';
|
import Rectangle3 from '@/assets/Rectangle-201.png';
|
||||||
import { Combobox, Flex, ResolvedAddress, Text } from '@/components';
|
import {
|
||||||
|
Combobox,
|
||||||
|
Flex,
|
||||||
|
Icon,
|
||||||
|
IconName,
|
||||||
|
ResolvedAddress,
|
||||||
|
Text,
|
||||||
|
} from '@/components';
|
||||||
|
import { getDate, getRepositoryFromURL, getTimeSince } from '@/utils';
|
||||||
|
|
||||||
import { IndexedNFAStyles as S } from '../indexed-nfa.styles';
|
import { IndexedNFAStyles as S } from '../indexed-nfa.styles';
|
||||||
|
|
||||||
|
|
@ -54,10 +62,134 @@ const Header: React.FC = () => {
|
||||||
)}
|
)}
|
||||||
</Combobox>
|
</Combobox>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
{/* </Flex>
|
||||||
|
<HeaderData label="Owner">
|
||||||
|
<ResolvedAddress>{nfa.owner.id}</ResolvedAddress>
|
||||||
|
</HeaderData>
|
||||||
|
|
||||||
|
<S.Main.Divider.Elipse />
|
||||||
|
|
||||||
|
<HeaderData label="Created">{getDate(nfa.createdAt)}</HeaderData>
|
||||||
|
|
||||||
|
<S.Main.Divider.Elipse />
|
||||||
|
|
||||||
|
<HeaderData label="Access Points">
|
||||||
|
{nfa.accessPoints?.length ?? 0}
|
||||||
|
</HeaderData>
|
||||||
|
</Flex> */}
|
||||||
|
{/* <S.Main.Divider.Line /> */}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// const Description: React.FC = () => {
|
||||||
|
// const { nfa } = IndexedNFA.useContext();
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <>
|
||||||
|
// <S.Main.SectionHeading css={{ marginTop: 0 }}>
|
||||||
|
// Description
|
||||||
|
// </S.Main.SectionHeading>
|
||||||
|
// <S.Main.DataContainer as={S.Main.Paragraph}>
|
||||||
|
// {nfa.description}
|
||||||
|
// </S.Main.DataContainer>
|
||||||
|
// </>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// type DataWrapperProps = React.PropsWithChildren<{
|
||||||
|
// label: string | number;
|
||||||
|
// }>;
|
||||||
|
|
||||||
|
// const DataWrapper: React.FC<DataWrapperProps> = ({
|
||||||
|
// children,
|
||||||
|
// label,
|
||||||
|
// }: DataWrapperProps) => (
|
||||||
|
// <S.Main.DataContainer key={label} css={{ flex: 1, minWidth: '45%' }}>
|
||||||
|
// <Text css={{ color: '$slate12', fontWeight: 700 }}>{children || '-'}</Text>
|
||||||
|
// <Text css={{ color: '$slate11' }}>{label}</Text>
|
||||||
|
// </S.Main.DataContainer>
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const Traits: React.FC = () => {
|
||||||
|
// const { nfa } = IndexedNFA.useContext();
|
||||||
|
|
||||||
|
// const traitsToShow = useMemo(() => {
|
||||||
|
// return [
|
||||||
|
// [nfa.ENS, 'ENS'],
|
||||||
|
// [getRepositoryFromURL(nfa.gitRepository.id), 'Repository'],
|
||||||
|
// ['', 'Version'],
|
||||||
|
// [nfa.externalURL, 'Domain'],
|
||||||
|
// ];
|
||||||
|
// }, [nfa]);
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <>
|
||||||
|
// <S.Main.SectionHeading>Traits</S.Main.SectionHeading>
|
||||||
|
// <S.Main.DataList>
|
||||||
|
// {traitsToShow.map(([value, label]) => (
|
||||||
|
// <DataWrapper key={label} label={label}>
|
||||||
|
// {value}
|
||||||
|
// </DataWrapper>
|
||||||
|
// ))}
|
||||||
|
// </S.Main.DataList>
|
||||||
|
// </>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// type VerificationBannerProps = {
|
||||||
|
// verified: boolean;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const VerificationBanner: React.FC<VerificationBannerProps> = ({
|
||||||
|
// verified,
|
||||||
|
// }: VerificationBannerProps) => {
|
||||||
|
// const [text, icon] = useMemo<[string, IconName]>(() => {
|
||||||
|
// if (verified)
|
||||||
|
// return ['This Non Fungible Application is Verified.', 'verified'];
|
||||||
|
// return ['This Non Fungible Application is not Verified.', 'error'];
|
||||||
|
// }, [verified]);
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <S.Main.VerificationBanner verified={verified}>
|
||||||
|
// {text}
|
||||||
|
// <Icon
|
||||||
|
// name={icon}
|
||||||
|
// css={{
|
||||||
|
// fontSize: '3.5rem',
|
||||||
|
// color: '$black',
|
||||||
|
// position: 'absolute',
|
||||||
|
// right: 'calc(8% - 1.75rem)',
|
||||||
|
// zIndex: 1,
|
||||||
|
// }}
|
||||||
|
// />
|
||||||
|
// </S.Main.VerificationBanner>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const Verification: React.FC = () => {
|
||||||
|
// const { nfa } = IndexedNFA.useContext();
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <>
|
||||||
|
// <S.Main.SectionHeading>Verification</S.Main.SectionHeading>
|
||||||
|
// <VerificationBanner verified={nfa.verified} />
|
||||||
|
// <S.Main.DataList>
|
||||||
|
// <DataWrapper label="Verifier">
|
||||||
|
// {nfa.verifier ? (
|
||||||
|
// <ResolvedAddress>{nfa.verifier?.id}</ResolvedAddress>
|
||||||
|
// ) : (
|
||||||
|
// '-'
|
||||||
|
// )}
|
||||||
|
// </DataWrapper>
|
||||||
|
// <DataWrapper label="Repository">
|
||||||
|
// {getRepositoryFromURL(nfa.gitRepository.id)}
|
||||||
|
// </DataWrapper>
|
||||||
|
// </S.Main.DataList>
|
||||||
|
// </>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
const thumbnailMocks = [Rectangle1, Rectangle2, Rectangle3];
|
const thumbnailMocks = [Rectangle1, Rectangle2, Rectangle3];
|
||||||
// TODO: replace mocks with fetched data
|
// TODO: replace mocks with fetched data
|
||||||
const apMocks = new Array(20).fill(0).map((_, index) => ({
|
const apMocks = new Array(20).fill(0).map((_, index) => ({
|
||||||
|
|
@ -101,6 +233,68 @@ const AccessPointsListFragment: React.FC = () => {
|
||||||
</S.Main.AccessPoint.List>
|
</S.Main.AccessPoint.List>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
// const AccessPoints: React.FC = () => {
|
||||||
|
// const {
|
||||||
|
// nfa: { accessPoints },
|
||||||
|
// } = IndexedNFA.useContext();
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <>
|
||||||
|
// <S.Main.SectionHeading>Frontends</S.Main.SectionHeading>
|
||||||
|
// <S.Main.Table.Container>
|
||||||
|
// <S.Main.Table.Root>
|
||||||
|
// <colgroup>
|
||||||
|
// <col span={1} style={{ width: '9.5%' }} />
|
||||||
|
// <col span={1} style={{ width: '32.5%' }} />
|
||||||
|
// <col span={1} style={{ width: '32.5%' }} />
|
||||||
|
// <col span={1} style={{ width: '16%' }} />
|
||||||
|
// <col span={1} style={{ width: '9.5%' }} />
|
||||||
|
// </colgroup>
|
||||||
|
// <S.Main.Table.Head>
|
||||||
|
// <S.Main.Table.Row>
|
||||||
|
// <S.Main.Table.Data>
|
||||||
|
// <S.Main.Table.Marker />
|
||||||
|
// </S.Main.Table.Data>
|
||||||
|
// <S.Main.Table.Data>Domain</S.Main.Table.Data>
|
||||||
|
// <S.Main.Table.Data>Owner</S.Main.Table.Data>
|
||||||
|
// <S.Main.Table.Data>Created</S.Main.Table.Data>
|
||||||
|
// <S.Main.Table.Data />
|
||||||
|
// </S.Main.Table.Row>
|
||||||
|
// </S.Main.Table.Head>
|
||||||
|
// <S.Main.Table.Body>
|
||||||
|
// {accessPoints && accessPoints.length > 0 ? (
|
||||||
|
// accessPoints.map((item) => (
|
||||||
|
// <S.Main.Table.Row key={item.id}>
|
||||||
|
// <S.Main.Table.Data align="center">
|
||||||
|
// <S.Main.Table.Marker
|
||||||
|
// variant={item.contentVerified ? 'active' : 'inactive'}
|
||||||
|
// />
|
||||||
|
// </S.Main.Table.Data>
|
||||||
|
// <S.Main.Table.Data>{item.id}</S.Main.Table.Data>
|
||||||
|
// <S.Main.Table.Data>
|
||||||
|
// <ResolvedAddress>{item.owner.id}</ResolvedAddress>
|
||||||
|
// </S.Main.Table.Data>
|
||||||
|
// <S.Main.Table.Data>
|
||||||
|
// {getTimeSince(item.createdAt)}
|
||||||
|
// </S.Main.Table.Data>
|
||||||
|
// <S.Main.Table.Data>
|
||||||
|
// <Icon name="external-link" />
|
||||||
|
// </S.Main.Table.Data>
|
||||||
|
// </S.Main.Table.Row>
|
||||||
|
// ))
|
||||||
|
// ) : (
|
||||||
|
// <S.Main.Table.Row>
|
||||||
|
// <S.Main.Table.Data align="center" colSpan={5}>
|
||||||
|
// <Text>No results</Text>
|
||||||
|
// </S.Main.Table.Data>
|
||||||
|
// </S.Main.Table.Row>
|
||||||
|
// )}
|
||||||
|
// </S.Main.Table.Body>
|
||||||
|
// </S.Main.Table.Root>
|
||||||
|
// </S.Main.Table.Container>
|
||||||
|
// </>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
export const IndexedNFAMainFragment: React.FC = () => {
|
export const IndexedNFAMainFragment: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,7 @@ import { useEffect } from 'react';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { App } from '@/app.context';
|
import { App } from '@/app.context';
|
||||||
import { getNFADocument } from '@/graphclient';
|
import { getNFADetailDocument } from '@/graphclient';
|
||||||
import { NFAMock } from '@/mocks';
|
|
||||||
import { AppLog } from '@/utils';
|
import { AppLog } from '@/utils';
|
||||||
import { parseNumberToHexColor } from '@/utils/color';
|
import { parseNumberToHexColor } from '@/utils/color';
|
||||||
|
|
||||||
|
|
@ -36,7 +35,7 @@ export const IndexedNFAView: React.FC = () => {
|
||||||
navigate('/', { replace: true });
|
navigate('/', { replace: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
const { loading, data = { token: {} } } = useQuery(getNFADocument, {
|
const { loading, data = { token: {} } } = useQuery(getNFADetailDocument, {
|
||||||
skip: id === undefined,
|
skip: id === undefined,
|
||||||
variables: {
|
variables: {
|
||||||
id: ethers.utils.hexlify(Number(id)),
|
id: ethers.utils.hexlify(Number(id)),
|
||||||
|
|
@ -55,9 +54,13 @@ export const IndexedNFAView: React.FC = () => {
|
||||||
return <IndexedNFASkeletonFragment />;
|
return <IndexedNFASkeletonFragment />;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replace NFAMock with real data from useQuery
|
if (!data.token) {
|
||||||
|
//TODO add 404 page
|
||||||
|
return <div>Token not found</div>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IndexedNFA.Provider nfa={{ ...NFAMock, ...data.token }}>
|
<IndexedNFA.Provider nfa={data.token}>
|
||||||
<S.Grid>
|
<S.Grid>
|
||||||
<IndexedNFAAsideFragment />
|
<IndexedNFAAsideFragment />
|
||||||
<IndexedNFAMainFragment />
|
<IndexedNFAMainFragment />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue