Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: list flies #3

Merged
merged 5 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
</p>

<h1 align="center">
Aether
aether
</h1>

<p align="center">
Journey into the Aether where storage defies conventional bounds.
Journey into the aether where storage defies conventional bounds.
</p>

<p align="center">
Aether is a modern file storage platform that implements a state-of-the-art Merkle tree structure to store multiple files.
aether is a modern file storage platform that implements a state-of-the-art Merkle tree structure to store multiple files.
</p>

<p align="center">
Expand Down Expand Up @@ -86,7 +86,7 @@ make setup
make
```

> ⚠️ **NOTE:** The `make` command will run/re-run `make install`, but will not overwrite any `.env.*` that may have been edited in section [1.2.](#22-setting-up-environment-variables-optional)
> ⚠️ **NOTE:** The `make` command will run/re-run `make setup`, but will not overwrite any `.env.*` that may have been edited in section [1.2.](#22-setting-up-environment-variables-optional)

2. Navigate to [http://localhost:8080](http://localhost:8080) to access the web portal.

Expand All @@ -105,8 +105,8 @@ make
| `make dev-web` | Runs the web app using `next dev`. Intended for development purposes only. |
| `make clean` | Deletes the build directory. |
| `make install` | Installs the yarn and golang dependencies. |
| `make run` | Checks if the apps are correctly configured and runs Docker Compose. |
| `make setup` | Creates the `.env.*` files to the `.config/` directory. |
| `make run` | Checks if the apps are correctly configured and runs Docker Compose. Intended for development purposes only. |
| `make setup` | Creates `.env.*` files in the `.config/` directory. |

<sup>[Back to top ^][table-of-contents]</sup>

Expand Down
1 change: 1 addition & 0 deletions app/@types/environment.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ declare namespace NodeJS {
readonly PORT: string;

// public
readonly NEXT_PUBLIC_CORE_URL: string;
readonly NEXT_PUBLIC_DESCRIPTION: string;
readonly NEXT_PUBLIC_LOG_LEVEL: string;
readonly NEXT_PUBLIC_TAGLINE: string;
Expand Down
4 changes: 2 additions & 2 deletions app/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const Header: FC<IProps> = ({ onNavigationClick }) => {
w="full"
>
{/*open navigation menu button*/}
<Tooltip label={`Open navigation menu`}>
<Tooltip label={`Open Navigation Menu`}>
<IconButton
_hover={{ bg: buttonHoverBackgroundColor }}
aria-label="Open navigation drawer"
Expand All @@ -56,7 +56,7 @@ const Header: FC<IProps> = ({ onNavigationClick }) => {
>
<IconButton
_hover={{ bg: buttonHoverBackgroundColor }}
aria-label="Change color mode"
aria-label="Change Color Mode"
color={defaultTextColor}
icon={colorMode === 'dark' ? <IoSunnyOutline /> : <IoMoonOutline />}
onClick={handlerColorChangeClick}
Expand Down
11 changes: 9 additions & 2 deletions app/components/Navigation/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
IoCheckmarkCircleOutline,
IoChevronBackOutline,
IoCloudUploadOutline,
IoListOutline,
} from 'react-icons/io5';

// components
Expand All @@ -27,6 +28,7 @@ import NavigationLinkItem from './NavigationLinkItem';
// constants
import {
DEFAULT_GAP,
FILES_ROUTE,
INDEX_ROUTE,
UPLOAD_ROUTE,
VERIFY_ROUTE,
Expand All @@ -53,6 +55,11 @@ const Navigation: FC<IProps> = ({ isOpen, onClose }) => {
label: 'Upload',
route: UPLOAD_ROUTE,
},
{
icon: IoListOutline,
label: 'Files',
route: FILES_ROUTE,
},
{
icon: IoCheckmarkCircleOutline,
label: 'Verify',
Expand Down Expand Up @@ -82,7 +89,7 @@ const Navigation: FC<IProps> = ({ isOpen, onClose }) => {
{/*icon*/}
<IconButton
_hover={{ bg: 'transparent' }}
aria-label="Go to hom epage"
aria-label="Go To Home"
color={primaryColor}
icon={<AetherIcon h={12} w={12} />}
onClick={handleHomeClick}
Expand All @@ -93,7 +100,7 @@ const Navigation: FC<IProps> = ({ isOpen, onClose }) => {
<Spacer />

{/*close navigation menu button*/}
<Tooltip label={`Close navigation menu`}>
<Tooltip label={`Close Menu`}>
<IconButton
_hover={{ bg: buttonHoverBackgroundColor }}
aria-label="Close navigation drawer"
Expand Down
18 changes: 8 additions & 10 deletions app/components/UploadCompleteModal/UploadCompleteModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import type { IProps } from './types';
// utils
import downloadJSONFile from '@app/utils/downloadJSONFile';

const UploadCompleteModal: FC<IProps> = ({ merkleTreeRootHash, onClose }) => {
const UploadCompleteModal: FC<IProps> = ({ onClose, uploadResponse }) => {
// hooks
const defaultTextColor: string = useDefaultTextColor();
const logger: ILogger = useLogger();
Expand All @@ -44,24 +44,22 @@ const UploadCompleteModal: FC<IProps> = ({ merkleTreeRootHash, onClose }) => {
const handleDownloadMerkleRoot = () => {
const _functionName: string = 'handleDownloadMerkleRoot';

if (!merkleTreeRootHash) {
if (!uploadResponse) {
logger.debug(
`${UploadCompleteModal.displayName}#${_functionName}: no merkle tree root hash found, ignoring`
);

return;
}

// create a data uri from the json and download ir
downloadJSONFile('root', {
root: merkleTreeRootHash,
});
// create a data uri from the json and download it - use the merkle root as the file name
downloadJSONFile(uploadResponse.root, uploadResponse);
};

return (
<Modal
closeOnOverlayClick={false}
isOpen={!!merkleTreeRootHash}
isOpen={!!uploadResponse}
onClose={onClose}
>
<ModalOverlay />
Expand All @@ -82,19 +80,19 @@ const UploadCompleteModal: FC<IProps> = ({ merkleTreeRootHash, onClose }) => {

{/*merkle tree root hash*/}
<HStack alignItems="center" spacing={1} w="full">
{!merkleTreeRootHash ? (
{!uploadResponse ? (
<Skeleton height="20px" w="full" />
) : (
<>
{/*merkle tree root hash*/}
<Code borderRadius="md" flexGrow={1} wordBreak="break-word">
{merkleTreeRootHash}
{uploadResponse.root}
</Code>

{/*copy button*/}
<CopyIconButton
ariaLabel={`Copy hash`}
value={merkleTreeRootHash}
value={uploadResponse.root}
/>
</>
)}
Expand Down
5 changes: 4 additions & 1 deletion app/components/UploadCompleteModal/types/IProps.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// types
import type { IUploadResponse } from '@app/types';

interface IProps {
merkleTreeRootHash: string | null;
onClose: () => void;
uploadResponse: IUploadResponse | null;
}

export default IProps;
3 changes: 3 additions & 0 deletions app/constants/Paths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const FILES_PATH: string = 'files';
export const UPLOAD_PATH: string = 'upload';
export const VERSIONS_PATH: string = 'versions';
1 change: 1 addition & 0 deletions app/constants/Routes.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const FILES_ROUTE: string = '/files';
export const INDEX_ROUTE: string = '/';
export const UPLOAD_ROUTE: string = '/upload';
export const VERIFY_ROUTE: string = '/verify';
1 change: 1 addition & 0 deletions app/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './Dimensions';
export * from './Links';
export * from './Paths';
export * from './Routes';
export * from './Styles';
6 changes: 6 additions & 0 deletions app/enums/LeafPositionEnum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
enum LeafPositionEnum {
Left = 0,
Right = 1,
}

export default LeafPositionEnum;
1 change: 1 addition & 0 deletions app/enums/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as LeafPositionEnum } from './LeafPositionEnum';
179 changes: 179 additions & 0 deletions app/files/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
'use client';
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Code,
Heading,
HStack,
IconButton,
Skeleton,
Spacer,
Stack,
Text,
Tooltip,
VStack,
} from '@chakra-ui/react';
import { NextPage } from 'next';
import React from 'react';
import { IoDownloadOutline } from 'react-icons/io5';

// components
import CopyIconButton from '@app/components/CopyIconButton';

// constants
import { DEFAULT_GAP } from '@app/constants';

// hooks
import useButtonHoverBackgroundColor from '@app/hooks/useButtonHoverBackgroundColor';
import useDefaultTextColor from '@app/hooks/useDefaultTextColor';
import useFiles from '@app/hooks/useFiles';
import useSubTextColor from '@app/hooks/useSubTextColor';

// types
import type { IFileResponse } from '@app/types';

// utils
import downloadJSONFile from '@app/utils/downloadJSONFile';

const FilesPage: NextPage = () => {
// hooks
const buttonHoverBackgroundColor: string = useButtonHoverBackgroundColor();
const defaultTextColor: string = useDefaultTextColor();
const subTextColor: string = useSubTextColor();
const { files, loading } = useFiles();
// handlers
const handleDownloadProofClick = (file: IFileResponse) => () =>
downloadJSONFile(file.hash, file.proof);
// renders
const renderContent = () => {
let fileKeys: string[];

if (loading) {
return Array.from({ length: 3 }, (_, index) => (
<Skeleton h="20px" key={`files-page-skeleton-item-${index}`} w="full" />
));
}

if (files) {
fileKeys = Object.keys(files);

if (fileKeys.length > 0) {
return (
<Accordion allowMultiple={true} allowToggle={true} w="full">
{fileKeys.map((key, fileKeyIndex) => (
<AccordionItem key={`files-page-${key}-${fileKeyIndex}`}>
{/*accordian button*/}
<AccordionButton p={DEFAULT_GAP / 2}>
<Code
color={defaultTextColor}
fontSize="md"
maxW={650}
noOfLines={1}
textAlign="left"
>
{key}
</Code>

<Spacer />

<AccordionIcon />
</AccordionButton>

{/*list of files*/}
<AccordionPanel p={0}>
{files[key].map((file, index) => (
<HStack
alignItems="center"
justifyContent="space-between"
key={`files-page-${key}-item-${index}`}
p={DEFAULT_GAP / 2}
spacing={DEFAULT_GAP / 3}
w="full"
>
{/*name*/}
<Text
color={subTextColor}
fontSize="sm"
maxW={500}
noOfLines={1}
textAlign="left"
>
{file.name}
</Text>

<Spacer />

{/*copy hash button*/}
<CopyIconButton
ariaLabel={`Copy Hash`}
size="md"
value={file.hash}
/>

{/*download proof button*/}
<Tooltip label={`Download Proof`}>
<IconButton
_hover={{ bg: buttonHoverBackgroundColor }}
aria-label="Download file proof"
color={defaultTextColor}
icon={<IoDownloadOutline />}
onClick={handleDownloadProofClick(file)}
size="md"
variant="ghost"
/>
</Tooltip>
</HStack>
))}
</AccordionPanel>
</AccordionItem>
))}
</Accordion>
);
}
}

// when there are no files returned
return (
<Stack alignItems="center" flexGrow={1} justify="center" w="full">
<Text color={defaultTextColor} textAlign="center">
{`No files found!`}
</Text>
</Stack>
);
};

return (
<VStack
alignItems="center"
justifyContent="flex-start"
flexGrow={1}
spacing={DEFAULT_GAP}
w="full"
>
{/*heading*/}
<Heading color={defaultTextColor} size="lg" textAlign="center" w="full">
{`Files`}
</Heading>

{/*description*/}
<Text color={defaultTextColor} size="md" textAlign="center" w="full">
{`Below is a list of files, grouped by their merkle tree roots. You can download a file's proof and use the root you received to verify the file's integrity.`}
</Text>

<VStack
alignItems="center"
flexGrow={1}
justify="flex-start"
spacing={DEFAULT_GAP - 2}
w="full"
>
{renderContent()}
</VStack>
</VStack>
);
};

export default FilesPage;
2 changes: 2 additions & 0 deletions app/hooks/useFiles/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './useFiles';
export * from './types';
Loading
Loading