Commit 0891adbd authored by isstuev's avatar isstuev

design fixes 1

parent a0b15f53
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 30 30">
<path fill="#4A5568" fill-rule="evenodd" d="M7.904 22.831c.335.102.681.153 1.029.152a3.59 3.59 0 0 0 1.907-.583 4.14 4.14 0 0 0 1.17-1.155 4.666 4.666 0 0 0 .68-1.57l.165-.688h4.287l.128.704c.132.569.363 1.102.68 1.57.319.468.716.86 1.171 1.155a3.61 3.61 0 0 0 1.444.548 3.483 3.483 0 0 0 1.521-.117c1.011-.32 1.87-1.07 2.39-2.092.52-1.021.66-2.23.39-3.366L23.2 10.31a4.69 4.69 0 0 0-.682-1.569 4.16 4.16 0 0 0-1.169-1.156 3.61 3.61 0 0 0-1.444-.548 3.483 3.483 0 0 0-1.52.117 3.793 3.793 0 0 0-1.442.832 4.34 4.34 0 0 0-1.017 1.413H14.07a4.357 4.357 0 0 0-1.018-1.411 3.814 3.814 0 0 0-1.44-.834 3.483 3.483 0 0 0-1.521-.117 3.6 3.6 0 0 0-1.444.548 4.14 4.14 0 0 0-1.173 1.162 4.668 4.668 0 0 0-.678 1.58L5.132 17.39a4.944 4.944 0 0 0 .393 3.354c.518 1.017 1.372 1.767 2.379 2.088ZM9.36 8.967c.375-.24.798-.366 1.23-.368.216 0 .433.033.642.096.39.123.747.349 1.042.657.296.309.522.691.659 1.117l.171.527h3.787l.171-.527a2.88 2.88 0 0 1 .655-1.116c.294-.309.65-.534 1.039-.658a2.22 2.22 0 0 1 .963-.073 2.3 2.3 0 0 1 .916.345c.29.19.544.442.746.742.203.3.35.643.432 1.008l1.665 7.064a3.162 3.162 0 0 1-.237 2.16c-.33.657-.88 1.141-1.527 1.348-.314.095-.642.12-.964.073a2.298 2.298 0 0 1-.916-.345 2.675 2.675 0 0 1-.749-.742 3.016 3.016 0 0 1-.437-1.008l-.435-1.878h-6.43l-.444 1.878a2.982 2.982 0 0 1-.435 1.01 2.64 2.64 0 0 1-.75.74 2.28 2.28 0 0 1-.912.346 2.199 2.199 0 0 1-.96-.074c-.648-.209-1.196-.693-1.527-1.35a3.179 3.179 0 0 1-.245-2.158l1.664-7.064c.173-.736.6-1.365 1.186-1.75ZM20 12.287a.714.714 0 1 1-1.43.001.714.714 0 0 1 1.43 0ZM9.918 14.906a1.43 1.43 0 1 0 1.588-2.377 1.43 1.43 0 0 0-1.588 2.377Zm9.367.955a.714.714 0 1 0 0-1.429.714.714 0 0 0 0 1.43Zm-.714-2.143a.714.714 0 1 1-1.429 0 .714.714 0 0 1 1.429 0Zm2.143.714a.714.714 0 1 0 0-1.429.714.714 0 0 0 0 1.43Z" clip-rule="evenodd"/>
<path fill="#000" fill-opacity=".2" fill-rule="evenodd" d="M7.904 22.831c.335.102.681.153 1.029.152a3.59 3.59 0 0 0 1.907-.583 4.14 4.14 0 0 0 1.17-1.155 4.666 4.666 0 0 0 .68-1.57l.165-.688h4.287l.128.704c.132.569.363 1.102.68 1.57.319.468.716.86 1.171 1.155a3.61 3.61 0 0 0 1.444.548 3.483 3.483 0 0 0 1.521-.117c1.011-.32 1.87-1.07 2.39-2.092.52-1.021.66-2.23.39-3.366L23.2 10.31a4.69 4.69 0 0 0-.682-1.569 4.16 4.16 0 0 0-1.169-1.156 3.61 3.61 0 0 0-1.444-.548 3.483 3.483 0 0 0-1.52.117 3.793 3.793 0 0 0-1.442.832 4.34 4.34 0 0 0-1.017 1.413H14.07a4.357 4.357 0 0 0-1.018-1.411 3.814 3.814 0 0 0-1.44-.834 3.483 3.483 0 0 0-1.521-.117 3.6 3.6 0 0 0-1.444.548 4.14 4.14 0 0 0-1.173 1.162 4.668 4.668 0 0 0-.678 1.58L5.132 17.39a4.944 4.944 0 0 0 .393 3.354c.518 1.017 1.372 1.767 2.379 2.088ZM9.36 8.967c.375-.24.798-.366 1.23-.368.216 0 .433.033.642.096.39.123.747.349 1.042.657.296.309.522.691.659 1.117l.171.527h3.787l.171-.527a2.88 2.88 0 0 1 .655-1.116c.294-.309.65-.534 1.039-.658a2.22 2.22 0 0 1 .963-.073 2.3 2.3 0 0 1 .916.345c.29.19.544.442.746.742.203.3.35.643.432 1.008l1.665 7.064a3.162 3.162 0 0 1-.237 2.16c-.33.657-.88 1.141-1.527 1.348-.314.095-.642.12-.964.073a2.298 2.298 0 0 1-.916-.345 2.675 2.675 0 0 1-.749-.742 3.016 3.016 0 0 1-.437-1.008l-.435-1.878h-6.43l-.444 1.878a2.982 2.982 0 0 1-.435 1.01 2.64 2.64 0 0 1-.75.74 2.28 2.28 0 0 1-.912.346 2.199 2.199 0 0 1-.96-.074c-.648-.209-1.196-.693-1.527-1.35a3.179 3.179 0 0 1-.245-2.158l1.664-7.064c.173-.736.6-1.365 1.186-1.75ZM20 12.287a.714.714 0 1 1-1.43.001.714.714 0 0 1 1.43 0ZM9.918 14.906a1.43 1.43 0 1 0 1.588-2.377 1.43 1.43 0 0 0-1.588 2.377Zm9.367.955a.714.714 0 1 0 0-1.429.714.714 0 0 0 0 1.43Zm-.714-2.143a.714.714 0 1 1-1.429 0 .714.714 0 0 1 1.429 0Zm2.143.714a.714.714 0 1 0 0-1.429.714.714 0 0 0 0 1.43Z" clip-rule="evenodd"/>
</svg>
...@@ -38,6 +38,7 @@ dayjs.extend(minMax); ...@@ -38,6 +38,7 @@ dayjs.extend(minMax);
dayjs.updateLocale('en', { dayjs.updateLocale('en', {
formats: { formats: {
llll: `MMM DD YYYY HH:mm:ss A (Z${ nbsp }UTC)`, llll: `MMM DD YYYY HH:mm:ss A (Z${ nbsp }UTC)`,
lll: 'MMM D, YYYY h:mm A',
}, },
relativeTime: { relativeTime: {
s: '1s', s: '1s',
......
...@@ -105,7 +105,7 @@ export default function useNavItems(): ReturnType { ...@@ -105,7 +105,7 @@ export default function useNavItems(): ReturnType {
const mudWorlds = config.features.mudFramework.isEnabled ? { const mudWorlds = config.features.mudFramework.isEnabled ? {
text: 'MUD worlds', text: 'MUD worlds',
nextRoute: { pathname: '/mud-worlds' as const }, nextRoute: { pathname: '/mud-worlds' as const },
icon: 'MUD', icon: 'MUD_menu',
isActive: pathname === '/mud-worlds', isActive: pathname === '/mud-worlds',
} : null; } : null;
......
...@@ -91,6 +91,7 @@ ...@@ -91,6 +91,7 @@
| "monaco/vyper" | "monaco/vyper"
| "moon-with-star" | "moon-with-star"
| "moon" | "moon"
| "MUD_menu"
| "MUD" | "MUD"
| "networks" | "networks"
| "networks/icon-placeholder" | "networks/icon-placeholder"
......
import { HStack, useColorModeValue, chakra } from '@chakra-ui/react'; import { Grid, Box, useColorModeValue, chakra, HStack } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
...@@ -39,25 +39,39 @@ const BreadcrumbItem = ({ text, href, isLast, scrollRef }: BreadcrumbItemProps) ...@@ -39,25 +39,39 @@ const BreadcrumbItem = ({ text, href, isLast, scrollRef }: BreadcrumbItemProps)
if (isLast) { if (isLast) {
return ( return (
<> <HStack gap={ 2 } overflow="hidden">
{ text } <Box
overflow="hidden"
whiteSpace="nowrap"
textOverflow="ellipsis"
>
{ text }
</Box>
<CopyToClipboard text={ href } type="link" mx={ 0 } color="text_secondary"/> <CopyToClipboard text={ href } type="link" mx={ 0 } color="text_secondary"/>
</> </HStack>
); );
} }
return ( return (
<> <HStack gap={ 2 } overflow="hidden">
<LinkInternal href={ href } onClick={ onLinkClick }>{ text }</LinkInternal> <LinkInternal
href={ href }
onClick={ onLinkClick }
overflow="hidden"
textOverflow="ellipsis"
whiteSpace="nowrap"
>
{ text }
</LinkInternal>
{ !isLast && <IconSvg name="arrows/east" boxSize={ 6 } color={ iconColor }/> } { !isLast && <IconSvg name="arrows/east" boxSize={ 6 } color={ iconColor }/> }
</> </HStack>
); );
}; };
const AddressMudBreadcrumbs = (props: TableViewProps | RecordViewProps) => { const AddressMudBreadcrumbs = (props: TableViewProps | RecordViewProps) => {
const queryParams = { tab: 'mud', hash: props.hash }; const queryParams = { tab: 'mud', hash: props.hash };
return ( return (
<HStack gap={ 2 } className={ props.className }> <Grid templateColumns="20px auto auto auto" gap={ 2 } alignItems="center" className={ props.className }>
<IconSvg name="MUD" boxSize={ 5 } color="green.500"/> <IconSvg name="MUD" boxSize={ 5 } color="green.500"/>
<BreadcrumbItem <BreadcrumbItem
text="MUD World" text="MUD World"
...@@ -72,14 +86,14 @@ const AddressMudBreadcrumbs = (props: TableViewProps | RecordViewProps) => { ...@@ -72,14 +86,14 @@ const AddressMudBreadcrumbs = (props: TableViewProps | RecordViewProps) => {
/> />
{ ('recordId' in props) && ( { ('recordId' in props) && (
<BreadcrumbItem <BreadcrumbItem
text={ props.tableName } text={ props.recordName }
href={ route({ pathname: '/address/[hash]', query: { ...queryParams, table_id: props.tableId, record_id: props.recordId } }) } href={ route({ pathname: '/address/[hash]', query: { ...queryParams, table_id: props.tableId, record_id: props.recordId } }) }
isLast isLast
scrollRef={ props.scrollRef } scrollRef={ props.scrollRef }
/> />
) } ) }
</HStack> </Grid>
); );
}; };
......
...@@ -45,7 +45,7 @@ const AddressMudRecord = ({ tableId, recordId, isQueryEnabled = true, scrollRef ...@@ -45,7 +45,7 @@ const AddressMudRecord = ({ tableId, recordId, isQueryEnabled = true, scrollRef
<AddressMudBreadcrumbs <AddressMudBreadcrumbs
hash={ hash } hash={ hash }
tableId={ tableId } tableId={ tableId }
tableName={ data?.table.table_name } tableName={ data?.table.table_full_name }
recordId={ recordId } recordId={ recordId }
recordName={ data.record.id } recordName={ data.record.id }
mb={ 6 } mb={ 6 }
...@@ -53,16 +53,16 @@ const AddressMudRecord = ({ tableId, recordId, isQueryEnabled = true, scrollRef ...@@ -53,16 +53,16 @@ const AddressMudRecord = ({ tableId, recordId, isQueryEnabled = true, scrollRef
/> />
) } ) }
<Table borderRadius="8px"> <Table borderRadius="8px" style={{ tableLayout: 'auto' }} width="100%">
{ data?.schema.key_names.length && data?.schema.key_names.map((keyName, index) => ( { data?.schema.key_names.length && data?.schema.key_names.map((keyName, index) => (
<Tr key={ keyName }> <Tr key={ keyName } borderBottomStyle={ index === data.schema.key_names.length - 1 ? 'hidden' : 'solid' }>
<Td fontWeight={ 600 }> <Td fontWeight={ 600 } whiteSpace="nowrap">
{ keyName } ({ data.schema.key_types[index] }) { keyName } ({ data.schema.key_types[index] })
</Td> </Td>
<Td colSpan={ 2 }> <Td colSpan={ 2 }>
<Flex justifyContent="space-between"> <Flex justifyContent="space-between">
<TruncatedValue value={ data.record.decoded[keyName] } mr={ 2 }/> <TruncatedValue value={ data.record.decoded[keyName] } mr={ 2 }/>
{ index === 0 && <Box color="text_secondary">{ dayjs(data.record.timestamp).format('llll') }</Box> } { index === 0 && <Box color="text_secondary">{ dayjs(data.record.timestamp).format('lll') }</Box> }
</Flex> </Flex>
</Td> </Td>
</Tr> </Tr>
...@@ -72,13 +72,17 @@ const AddressMudRecord = ({ tableId, recordId, isQueryEnabled = true, scrollRef ...@@ -72,13 +72,17 @@ const AddressMudRecord = ({ tableId, recordId, isQueryEnabled = true, scrollRef
<Tr backgroundColor={ valuesBgColor } borderBottomStyle="hidden"> <Tr backgroundColor={ valuesBgColor } borderBottomStyle="hidden">
<Td fontWeight={ 600 }>Field</Td> <Td fontWeight={ 600 }>Field</Td>
<Td fontWeight={ 600 }>Type</Td> <Td fontWeight={ 600 }>Type</Td>
<Td fontWeight={ 600 }>Value</Td> <Td fontWeight={ 600 } w="100%" wordBreak="break-all">Value</Td>
</Tr> </Tr>
{ data?.schema.value_names.map((valName, index) => ( { data?.schema.value_names.map((valName, index) => (
<Tr key={ valName } backgroundColor={ valuesBgColor } borderBottomStyle="hidden"> <Tr key={ valName } backgroundColor={ valuesBgColor } borderBottomStyle="hidden">
<Td>{ valName }</Td> <Td whiteSpace="nowrap">{ valName }</Td>
<Td>{ data.schema.value_types[index] }</Td> <Td>{ data.schema.value_types[index] }</Td>
<Td>{ data.record.decoded[valName] }</Td> <Td w="100%" wordBreak="break-all">
<Box>
{ data.record.decoded[valName] }
</Box>
</Td>
</Tr> </Tr>
)) } )) }
</> </>
......
...@@ -23,9 +23,20 @@ type Props = { ...@@ -23,9 +23,20 @@ type Props = {
toggleSorting: (key: AddressMudRecordsSorting['sort']) => void; toggleSorting: (key: AddressMudRecordsSorting['sort']) => void;
setFilters: React.Dispatch<React.SetStateAction<AddressMudRecordsFilter>>; setFilters: React.Dispatch<React.SetStateAction<AddressMudRecordsFilter>>;
filters: AddressMudRecordsFilter; filters: AddressMudRecordsFilter;
toggleTableHasHorisontalScroll: () => void;
scrollRef?: React.RefObject<HTMLDivElement>;
} }
const AddressMudRecordsTable = ({ data, top, sorting, toggleSorting, filters, setFilters }: Props) => { const AddressMudRecordsTable = ({
data,
top,
sorting,
toggleSorting,
filters,
setFilters,
toggleTableHasHorisontalScroll,
scrollRef,
}: Props) => {
const [ colsCutCount, setColsCutCount ] = React.useState<number>(0); const [ colsCutCount, setColsCutCount ] = React.useState<number>(0);
const [ isOpened, setIsOpened ] = useBoolean(false); const [ isOpened, setIsOpened ] = useBoolean(false);
const [ hasCut, setHasCut ] = useBoolean(true); const [ hasCut, setHasCut ] = useBoolean(true);
...@@ -33,13 +44,23 @@ const AddressMudRecordsTable = ({ data, top, sorting, toggleSorting, filters, se ...@@ -33,13 +44,23 @@ const AddressMudRecordsTable = ({ data, top, sorting, toggleSorting, filters, se
const tableRef = React.useRef<HTMLTableElement>(null); const tableRef = React.useRef<HTMLTableElement>(null);
const router = useRouter(); const router = useRouter();
const toggleIsOpen = React.useCallback(() => {
setIsOpened.toggle();
toggleTableHasHorisontalScroll();
}, [ setIsOpened, toggleTableHasHorisontalScroll ]);
const onRecordClick = React.useCallback((e: React.MouseEvent) => { const onRecordClick = React.useCallback((e: React.MouseEvent) => {
const newQuery = { const newQuery = {
...router.query, ...router.query,
record_id: e.currentTarget.getAttribute('data-id') as string, record_id: e.currentTarget.getAttribute('data-id') as string,
}; };
router.push({ pathname: router.pathname, query: newQuery }, undefined, { shallow: true }); router.push({ pathname: router.pathname, query: newQuery }, undefined, { shallow: true });
}, [ router ]); window.setTimeout(() => {
// cannot do scroll instantly, have to wait a little
scrollRef?.current?.scrollIntoView({ behavior: 'smooth' });
}, 500);
}, [ router, scrollRef ]);
const handleFilterChange = React.useCallback((field: keyof AddressMudRecordsFilter) => (val: string) => { const handleFilterChange = React.useCallback((field: keyof AddressMudRecordsFilter) => (val: string) => {
setFilters(prev => { setFilters(prev => {
...@@ -88,9 +109,10 @@ const AddressMudRecordsTable = ({ data, top, sorting, toggleSorting, filters, se ...@@ -88,9 +109,10 @@ const AddressMudRecordsTable = ({ data, top, sorting, toggleSorting, filters, se
const values = (isOpened || !hasCut) ? data.schema.value_names : data.schema.value_names.slice(0, colsCutCount - data.schema.key_names.length); const values = (isOpened || !hasCut) ? data.schema.value_names : data.schema.value_names.slice(0, colsCutCount - data.schema.key_names.length);
return ( return (
<Box maxW="100%" overflowX="scroll" whiteSpace="nowrap"> // can't implement both horisontal table scroll and sticky header
<Box maxW="100%" overflowX={ isOpened ? 'scroll' : 'unset' } whiteSpace="nowrap">
<Table variant="simple" size="sm" style={{ tableLayout: 'fixed' }} ref={ tableRef }> <Table variant="simple" size="sm" style={{ tableLayout: 'fixed' }} ref={ tableRef }>
<Thead top={ top } display="table" w="100%"> <Thead top={ isOpened ? 0 : top } display={ isOpened ? 'table' : 'table-header-group' } w="100%">
<Tr > <Tr >
{ keys.map((keyName, index) => { { keys.map((keyName, index) => {
const text = getNameTypeText(keyName, data.schema.key_types[index]); const text = getNameTypeText(keyName, data.schema.key_types[index]);
...@@ -120,18 +142,18 @@ const AddressMudRecordsTable = ({ data, top, sorting, toggleSorting, filters, se ...@@ -120,18 +142,18 @@ const AddressMudRecordsTable = ({ data, top, sorting, toggleSorting, filters, se
{ capitalizeFirstLetter(valName) } ({ data.schema.value_types[index] }) { capitalizeFirstLetter(valName) } ({ data.schema.value_types[index] })
</Th> </Th>
)) } )) }
{ hasCut && !isOpened && <Th width={ cutWidth }><Link onClick={ setIsOpened.on }>...</Link></Th> } { hasCut && !isOpened && <Th width={ cutWidth }><Link onClick={ toggleIsOpen }>...</Link></Th> }
<Th { ...thStyles }>Modified</Th> <Th { ...thStyles }>Modified</Th>
{ hasCut && isOpened && <Th width={ cutWidth }><Link onClick={ setIsOpened.off }>...</Link></Th> } { hasCut && isOpened && <Th width={ cutWidth }><Link onClick={ toggleIsOpen }>...</Link></Th> }
</Tr> </Tr>
</Thead> </Thead>
<Tbody display="table" w="100%"> <Tbody display={ isOpened ? 'table' : 'table-row-group' } w="100%">
{ data.items.map((item) => ( { data.items.map((item) => (
<Tr key={ item.id }> <Tr key={ item.id }>
{ keys.map((keyName, index) => ( { keys.map((keyName, index) => (
<Td key={ keyName } backgroundColor={ keyBgColor } { ...tdStyles }> <Td key={ keyName } backgroundColor={ keyBgColor } { ...tdStyles }>
{ index === 0 ? { index === 0 ?
<Link onClick={ onRecordClick } data-id={ item.id }>{ item.decoded[keyName].toString() }</Link> : <Link onClick={ onRecordClick } data-id={ item.id } fontWeight={ 700 }>{ item.decoded[keyName].toString() }</Link> :
item.decoded[keyName].toString() item.decoded[keyName].toString()
} }
</Td> </Td>
...@@ -139,7 +161,7 @@ const AddressMudRecordsTable = ({ data, top, sorting, toggleSorting, filters, se ...@@ -139,7 +161,7 @@ const AddressMudRecordsTable = ({ data, top, sorting, toggleSorting, filters, se
{ values.map((valName) => { values.map((valName) =>
<Td key={ valName } { ...tdStyles }>{ item.decoded[valName].toString() }</Td>) } <Td key={ valName } { ...tdStyles }>{ item.decoded[valName].toString() }</Td>) }
{ hasCut && !isOpened && <Td width={ cutWidth }></Td> } { hasCut && !isOpened && <Td width={ cutWidth }></Td> }
<Td { ...tdStyles }>{ dayjs(item.timestamp).format('llll') }</Td> <Td { ...tdStyles } color="text_secondary">{ dayjs(item.timestamp).format('lll') }</Td>
{ hasCut && isOpened && <Td width={ cutWidth }></Td> } { hasCut && isOpened && <Td width={ cutWidth }></Td> }
</Tr> </Tr>
)) } )) }
......
import { Box, HStack, Hide, Show, Tag, TagCloseButton, chakra } from '@chakra-ui/react'; import { Box, HStack, Hide, Show, Tag, TagCloseButton, chakra, useBoolean } from '@chakra-ui/react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
...@@ -6,7 +6,7 @@ import type { AddressMudRecordsFilter, AddressMudRecordsSorting } from 'types/ap ...@@ -6,7 +6,7 @@ import type { AddressMudRecordsFilter, AddressMudRecordsSorting } from 'types/ap
import { apos, nbsp } from 'lib/html-entities'; import { apos, nbsp } from 'lib/html-entities';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
import ActionBar from 'ui/shared/ActionBar'; import ActionBar, { ACTION_BAR_HEIGHT_DESKTOP } from 'ui/shared/ActionBar';
import ContentLoader from 'ui/shared/ContentLoader'; import ContentLoader from 'ui/shared/ContentLoader';
import DataListDisplay from 'ui/shared/DataListDisplay'; import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/pagination/Pagination'; import Pagination from 'ui/shared/pagination/Pagination';
...@@ -31,6 +31,7 @@ const AddressMudTable = ({ scrollRef, tableId, isQueryEnabled = true }: Props) = ...@@ -31,6 +31,7 @@ const AddressMudTable = ({ scrollRef, tableId, isQueryEnabled = true }: Props) =
const [ sorting, setSorting ] = const [ sorting, setSorting ] =
React.useState<AddressMudRecordsSorting | undefined>(getSortParamsFromQuery<AddressMudRecordsSorting>(router.query, SORT_SEQUENCE)); React.useState<AddressMudRecordsSorting | undefined>(getSortParamsFromQuery<AddressMudRecordsSorting>(router.query, SORT_SEQUENCE));
const [ filters, setFilters ] = React.useState<AddressMudRecordsFilter>({}); const [ filters, setFilters ] = React.useState<AddressMudRecordsFilter>({});
const [ tableHasHorisontalScroll, setTableHasHorisontalScroll ] = useBoolean(false);
const hash = getQueryParamString(router.query.hash); const hash = getQueryParamString(router.query.hash);
...@@ -60,14 +61,20 @@ const AddressMudTable = ({ scrollRef, tableId, isQueryEnabled = true }: Props) = ...@@ -60,14 +61,20 @@ const AddressMudTable = ({ scrollRef, tableId, isQueryEnabled = true }: Props) =
}); });
}, []); }, []);
const hasActiveFilters = Object.values(filters).some(Boolean);
const actionBatHeight = React.useMemo(() => {
const heightWithoutFilters = pagination.isVisible ? ACTION_BAR_HEIGHT_DESKTOP : 60;
return hasActiveFilters ? heightWithoutFilters + 44 : heightWithoutFilters;
}, [ pagination.isVisible, hasActiveFilters ]);
if (isLoading) { if (isLoading) {
return <ContentLoader/>; return <ContentLoader/>;
} }
const hasActiveFilters = Object.values(filters).some(Boolean);
const filtersTags = hasActiveFilters ? ( const filtersTags = hasActiveFilters ? (
<HStack gap={ 3 }> <HStack gap={ 3 } mb={ 1 }>
{ Object.entries(filters).map(([ key, value ]) => { { Object.entries(filters).map(([ key, value ]) => {
const index = key as FilterKeys === 'filter_key0' ? 0 : 1; const index = key as FilterKeys === 'filter_key0' ? 0 : 1;
return ( return (
...@@ -87,7 +94,7 @@ const AddressMudTable = ({ scrollRef, tableId, isQueryEnabled = true }: Props) = ...@@ -87,7 +94,7 @@ const AddressMudTable = ({ scrollRef, tableId, isQueryEnabled = true }: Props) =
) : null; ) : null;
const actionBar = ( const actionBar = (
<ActionBar mt={ -6 } showShadow justifyContent="space-between"> <ActionBar mt={ -6 } showShadow={ tableHasHorisontalScroll } justifyContent="space-between" alignItems={ hasActiveFilters ? 'start' : 'center' }>
<Box> <Box>
{ data && ( { data && (
<AddressMudBreadcrumbs <AddressMudBreadcrumbs
...@@ -95,7 +102,7 @@ const AddressMudTable = ({ scrollRef, tableId, isQueryEnabled = true }: Props) = ...@@ -95,7 +102,7 @@ const AddressMudTable = ({ scrollRef, tableId, isQueryEnabled = true }: Props) =
tableId={ tableId } tableId={ tableId }
tableName={ data?.table.table_full_name } tableName={ data?.table.table_full_name }
scrollRef={ scrollRef } scrollRef={ scrollRef }
mb={ 3 } mb={ hasActiveFilters ? 4 : 0 }
/> />
) } ) }
{ filtersTags } { filtersTags }
...@@ -109,13 +116,13 @@ const AddressMudTable = ({ scrollRef, tableId, isQueryEnabled = true }: Props) = ...@@ -109,13 +116,13 @@ const AddressMudTable = ({ scrollRef, tableId, isQueryEnabled = true }: Props) =
<Hide below="lg" ssr={ false }> <Hide below="lg" ssr={ false }>
<AddressMudRecordsTable <AddressMudRecordsTable
data={ data } data={ data }
// can't implement both horisontal table scroll and sticky header top={ actionBatHeight }
// top={ pagination.isVisible ? ACTION_BAR_HEIGHT_DESKTOP : 60 }
top={ 0 }
sorting={ sorting } sorting={ sorting }
toggleSorting={ toggleSorting } toggleSorting={ toggleSorting }
setFilters={ setFilters } setFilters={ setFilters }
filters={ filters } filters={ filters }
toggleTableHasHorisontalScroll={ setTableHasHorisontalScroll.toggle }
scrollRef={ scrollRef }
/> />
</Hide> </Hide>
<Show below="lg" ssr={ false }> <Show below="lg" ssr={ false }>
...@@ -142,6 +149,7 @@ const AddressMudTable = ({ scrollRef, tableId, isQueryEnabled = true }: Props) = ...@@ -142,6 +149,7 @@ const AddressMudTable = ({ scrollRef, tableId, isQueryEnabled = true }: Props) =
}} }}
content={ content } content={ content }
actionBar={ actionBar } actionBar={ actionBar }
showActionBarIfEmpty
/> />
); );
}; };
......
...@@ -69,6 +69,7 @@ const AddressMudTables = ({ scrollRef, isQueryEnabled = true }: Props) => { ...@@ -69,6 +69,7 @@ const AddressMudTables = ({ scrollRef, isQueryEnabled = true }: Props) => {
items={ data.items } items={ data.items }
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
top={ ACTION_BAR_HEIGHT_DESKTOP } top={ ACTION_BAR_HEIGHT_DESKTOP }
scrollRef={ scrollRef }
/> />
</Hide> </Hide>
<Show below="lg" ssr={ false }> <Show below="lg" ssr={ false }>
......
...@@ -11,10 +11,11 @@ type Props = { ...@@ -11,10 +11,11 @@ type Props = {
items: AddressMudTables['items']; items: AddressMudTables['items'];
isLoading: boolean; isLoading: boolean;
top: number; top: number;
scrollRef?: React.RefObject<HTMLDivElement>;
} }
//sorry for the naming //sorry for the naming
const AddressMudTablesTable = ({ items, isLoading, top }: Props) => { const AddressMudTablesTable = ({ items, isLoading, top, scrollRef }: Props) => {
return ( return (
<Table variant="simple" size="sm" style={{ tableLayout: 'auto' }}> <Table variant="simple" size="sm" style={{ tableLayout: 'auto' }}>
<Thead top={ top }> <Thead top={ top }>
...@@ -31,6 +32,7 @@ const AddressMudTablesTable = ({ items, isLoading, top }: Props) => { ...@@ -31,6 +32,7 @@ const AddressMudTablesTable = ({ items, isLoading, top }: Props) => {
key={ item.table.table_id + (isLoading ? String(index) : '') } key={ item.table.table_id + (isLoading ? String(index) : '') }
item={ item } item={ item }
isLoading={ isLoading } isLoading={ isLoading }
scrollRef={ scrollRef }
/> />
)) } )) }
</Tbody> </Tbody>
......
...@@ -10,9 +10,10 @@ import IconSvg from 'ui/shared/IconSvg'; ...@@ -10,9 +10,10 @@ import IconSvg from 'ui/shared/IconSvg';
type Props = { type Props = {
item: AddressMudTableItem; item: AddressMudTableItem;
isLoading: boolean; isLoading: boolean;
scrollRef?: React.RefObject<HTMLDivElement>;
}; };
const AddressMudTablesTableItem = ({ item, isLoading }: Props) => { const AddressMudTablesTableItem = ({ item, isLoading, scrollRef }: Props) => {
const [ isOpened, setIsOpened ] = useBoolean(false); const [ isOpened, setIsOpened ] = useBoolean(false);
const router = useRouter(); const router = useRouter();
...@@ -23,7 +24,11 @@ const AddressMudTablesTableItem = ({ item, isLoading }: Props) => { ...@@ -23,7 +24,11 @@ const AddressMudTablesTableItem = ({ item, isLoading }: Props) => {
table_id: e.currentTarget.getAttribute('data-id') as string, table_id: e.currentTarget.getAttribute('data-id') as string,
}; };
router.push({ pathname: router.pathname, query: newQuery }, undefined, { shallow: true }); router.push({ pathname: router.pathname, query: newQuery }, undefined, { shallow: true });
}, [ router ]); window.setTimeout(() => {
// cannot do scroll instantly, have to wait a little
scrollRef?.current?.scrollIntoView({ behavior: 'smooth' });
}, 500);
}, [ router, scrollRef ]);
return ( return (
<> <>
...@@ -62,13 +67,13 @@ const AddressMudTablesTableItem = ({ item, isLoading }: Props) => { ...@@ -62,13 +67,13 @@ const AddressMudTablesTableItem = ({ item, isLoading }: Props) => {
</Tr> </Tr>
{ isOpened && ( { isOpened && (
<Tr> <Tr>
<Td></Td> <Td pt={ 0 }></Td>
<Td colSpan={ 3 }> <Td colSpan={ 3 } pt={ 0 }>
<Table> <Table>
{ Boolean(item.schema.key_names.length) && ( { Boolean(item.schema.key_names.length) && (
<Tr> <Tr>
<Td width="80px" fontSize="sm" fontWeight={ 600 }>Key</Td> <Td width="80px" fontSize="sm" fontWeight={ 600 } py={ 2 }>Key</Td>
<Td> <Td py={ 2 }>
<VStack gap={ 1 } alignItems="start"> <VStack gap={ 1 } alignItems="start">
{ item.schema.key_names.map((name, index) => ( { item.schema.key_names.map((name, index) => (
<Tag key={ name }> <Tag key={ name }>
...@@ -80,8 +85,8 @@ const AddressMudTablesTableItem = ({ item, isLoading }: Props) => { ...@@ -80,8 +85,8 @@ const AddressMudTablesTableItem = ({ item, isLoading }: Props) => {
</Tr> </Tr>
) } ) }
<Tr borderBottomStyle="hidden"> <Tr borderBottomStyle="hidden">
<Td width="80px" fontSize="sm" fontWeight={ 600 }>Value</Td> <Td width="80px" fontSize="sm" fontWeight={ 600 } py={ 2 }>Value</Td>
<Td fontSize="sm"> <Td fontSize="sm" py={ 2 }>
<VStack gap={ 1 } alignItems="start"> <VStack gap={ 1 } alignItems="start">
{ item.schema.value_names.map((name, index) => ( { item.schema.value_names.map((name, index) => (
<Text key={ name }> <Text key={ name }>
......
...@@ -42,7 +42,7 @@ const NameDomainsListItem = ({ ...@@ -42,7 +42,7 @@ const NameDomainsListItem = ({
<ListItemMobileGrid.Label isLoading={ isLoading }>Registered on</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Registered on</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<Skeleton isLoaded={ !isLoading }> <Skeleton isLoaded={ !isLoading }>
<div>{ dayjs(registrationDate).format('MMM DD YYYY HH:mm:ss A') }</div> <div>{ dayjs(registrationDate).format('lll') }</div>
<div> { dayjs(registrationDate).fromNow() }</div> <div> { dayjs(registrationDate).fromNow() }</div>
</Skeleton> </Skeleton>
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
...@@ -54,7 +54,7 @@ const NameDomainsListItem = ({ ...@@ -54,7 +54,7 @@ const NameDomainsListItem = ({
<ListItemMobileGrid.Label isLoading={ isLoading }>Expiration date</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Expiration date</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<Skeleton isLoaded={ !isLoading } whiteSpace="pre-wrap"> <Skeleton isLoaded={ !isLoading } whiteSpace="pre-wrap">
<div>{ dayjs(expiryDate).format('MMM DD YYYY HH:mm:ss A') } </div> <div>{ dayjs(expiryDate).format('lll') } </div>
<NameDomainExpiryStatus date={ expiryDate }/> <NameDomainExpiryStatus date={ expiryDate }/>
</Skeleton> </Skeleton>
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
......
...@@ -32,7 +32,7 @@ const NameDomainsTableItem = ({ ...@@ -32,7 +32,7 @@ const NameDomainsTableItem = ({
<Td verticalAlign="middle" pl={ 9 }> <Td verticalAlign="middle" pl={ 9 }>
{ registrationDate && ( { registrationDate && (
<Skeleton isLoaded={ !isLoading }> <Skeleton isLoaded={ !isLoading }>
{ dayjs(registrationDate).format('MMM DD YYYY HH:mm:ss A') } { dayjs(registrationDate).format('lll') }
<chakra.span color="text_secondary"> { dayjs(registrationDate).fromNow() }</chakra.span> <chakra.span color="text_secondary"> { dayjs(registrationDate).fromNow() }</chakra.span>
</Skeleton> </Skeleton>
) } ) }
...@@ -40,7 +40,7 @@ const NameDomainsTableItem = ({ ...@@ -40,7 +40,7 @@ const NameDomainsTableItem = ({
<Td verticalAlign="middle"> <Td verticalAlign="middle">
{ expiryDate && ( { expiryDate && (
<Skeleton isLoaded={ !isLoading } whiteSpace="pre-wrap"> <Skeleton isLoaded={ !isLoading } whiteSpace="pre-wrap">
<span>{ dayjs(expiryDate).format('MMM DD YYYY HH:mm:ss A') } </span> <span>{ dayjs(expiryDate).format('lll') } </span>
<NameDomainExpiryStatus date={ expiryDate }/> <NameDomainExpiryStatus date={ expiryDate }/>
</Skeleton> </Skeleton>
) } ) }
......
...@@ -15,6 +15,7 @@ type Props = { ...@@ -15,6 +15,7 @@ type Props = {
items?: Array<unknown>; items?: Array<unknown>;
emptyText: string; emptyText: string;
actionBar?: React.ReactNode; actionBar?: React.ReactNode;
showActionBarIfEmpty?: boolean;
content: React.ReactNode; content: React.ReactNode;
className?: string; className?: string;
filterProps?: FilterProps; filterProps?: FilterProps;
...@@ -35,7 +36,12 @@ const DataListDisplay = (props: Props) => { ...@@ -35,7 +36,12 @@ const DataListDisplay = (props: Props) => {
} }
if (!props.items?.length) { if (!props.items?.length) {
return props.emptyText ? <Text className={ props.className }>{ props.emptyText }</Text> : null; return (
<>
{ props.showActionBarIfEmpty && props.actionBar }
{ props.emptyText && <Text className={ props.className }>{ props.emptyText }</Text> }
</>
);
} }
return ( return (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment