Skip to content

Commit

Permalink
Merge pull request #378 from node-real/feat/replace-object
Browse files Browse the repository at this point in the history
feat(dcellar-web-ui): object version history support
  • Loading branch information
aiden-cao authored Apr 29, 2024
2 parents 7112cb0 + e922662 commit 6b5fffa
Show file tree
Hide file tree
Showing 23 changed files with 452 additions and 102 deletions.
12 changes: 12 additions & 0 deletions apps/dcellar-web-ui/CHANGELOG.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
{
"name": "dcellar-web-ui",
"entries": [
{
"version": "1.1.0",
"tag": "dcellar-web-ui_v1.1.0",
"date": "Mon, 29 Apr 2024 06:35:57 GMT",
"comments": {
"minor": [
{
"comment": "Support object versions & replace object"
}
]
}
},
{
"version": "1.0.3",
"tag": "dcellar-web-ui_v1.0.3",
Expand Down
9 changes: 8 additions & 1 deletion apps/dcellar-web-ui/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# Change Log - dcellar-web-ui

This log was last generated on Mon, 22 Apr 2024 03:46:28 GMT and should not be manually modified.
This log was last generated on Mon, 29 Apr 2024 06:35:57 GMT and should not be manually modified.

## 1.1.0
Mon, 29 Apr 2024 06:35:57 GMT

### Minor changes

- Support object versions & replace object

## 1.0.3
Mon, 22 Apr 2024 03:46:28 GMT
Expand Down
2 changes: 1 addition & 1 deletion apps/dcellar-web-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dcellar-web-ui",
"version": "1.0.3",
"version": "1.1.0",
"private": false,
"scripts": {
"dev": "node ./scripts/dev.js -p 3200",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@ export const ListEmpty = memo<ListEmptyProps>(function ListEmpty({
<Container h={h}>
<Content>
{empty && (
<Flex flex={1} flexDirection={'column'} alignItems={'center'} justifyContent="center">
<Flex
textAlign={'center'}
flex={1}
flexDirection={'column'}
alignItems={'center'}
justifyContent="center"
>
<IconFont type={type} w={120} />
<Flex my={title && desc ? 16 : 0} flexDirection="column">
<Text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export const GlobalObjectUploadManager = memo<GlobalTasksProps>(
const objectSealingTimestamp = useAppSelector((root) => root.global.objectSealingTimestamp);
const tempAccountRecords = useAppSelector((root) => root.accounts.tempAccountRecords);
const bucketRecords = useAppSelector((root) => root.bucket.bucketRecords);
const objectRecords = useAppSelector((root) => root.object.objectRecords);
const hashTask = useAppSelector(selectHashTask(loginAccount));
const signTask = useAppSelector(selectSignTask(loginAccount));
const queue = useAppSelector(selectUploadQueue(loginAccount));
Expand Down Expand Up @@ -92,15 +93,27 @@ export const GlobalObjectUploadManager = memo<GlobalTasksProps>(

const runUploadTask = async (task: UploadObject) => {
if (authModal) return;
const isFolder = task.waitObject.name.endsWith('/');
const name = task.waitObject.name;
const isFolder = name.endsWith('/');
const { seedString } = await dispatch(getSpOffChainData(loginAccount, task.spAddress));
const endpoint = spRecords[task.spAddress].endpoint;
const fullObjectName = [
...task.prefixFolders,
task.waitObject.relativePath,
task.waitObject.name,
]
.filter(Boolean)
.join('/');
const key = `${task.bucketName}/${fullObjectName}`;
const sealed = objectRecords[key]?.ObjectInfo.ObjectStatus === 1;
const [uploadOptions, error1] = await getPutObjectRequestConfig(
task,
loginAccount,
seedString,
endpoint,
task.waitObject.file,
sealed,
fullObjectName,
);
if (!uploadOptions || error1) {
return dispatch(
Expand Down
9 changes: 9 additions & 0 deletions apps/dcellar-web-ui/src/facade/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import { ObjectMeta } from '@bnb-chain/greenfield-js-sdk/dist/esm/types/sp/Commo
import axios from 'axios';
import { XMLParser } from 'fast-xml-parser';
import { Connector } from 'wagmi';
import { ObjectVersion } from '@/store/slices/object';

export type DeliverResponse = Awaited<ReturnType<TxResponse['broadcast']>>;

Expand Down Expand Up @@ -638,6 +639,14 @@ export const getObjectMeta = async (
);
};

export const getObjectVersions = async (id: string): Promise<ObjectVersion[]> => {
const [result] = await axios
.get<{ result: ObjectVersion[] }>(`/api/versions/${id}`)
.then(resolve, commonFault);
if (!result) return [];
return result.data.result || [];
};

export type UpdateObjectTagsParams = {
address: string;
bucketName: string;
Expand Down
1 change: 1 addition & 0 deletions apps/dcellar-web-ui/src/hooks/useHandleFolderTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ export const useHandleFolderTree = () => {
size: file.size,
relativePath: relativePath,
lockFee: '',
isUpdate: false,
};

return waitObject;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const OptionItem = memo(function OptionItem({
<TD w={80} color={textColor}>
{meta && meta.FreeReadQuota ? formatBytes(meta.FreeReadQuota) : '--'}
</TD>
<TD w={144} color={textColor}>
<TD w={136} color={textColor}>
{meta && meta.MonthlyFreeQuota ? formatBytes(meta.MonthlyFreeQuota) : '--'}
</TD>
<TD $dot={access ? spLatency : 0} color={textColor}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export const SPSelector = memo<SPSelectorProps>(function SPSelector({ onChange }
<>
<TH w={216}>SP list ({total})</TH>
<TH w={80}>Free Quota</TH>
<TH w={144}>Free Monthly Quota</TH>
<TH w={136}>Free Monthly Quota</TH>
<TH w={80}>Latency</TH>
</>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const TD = styled(Box, transientOptions)<{ $dot?: number }>`
position: relative;
font-size: 14px;
font-weight: 400;
flex-shrink: 0;
${(props) =>
props.$dot &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ import { EMPTY_TX_HASH } from '@/modules/object/constant';
import { useAppDispatch, useAppSelector } from '@/store';
import { AccountInfo } from '@/store/slices/accounts';
import { TBucket, setBucketQuota } from '@/store/slices/bucket';
import { ObjectActionType, setObjectEditTagsData, setObjectOperation } from '@/store/slices/object';
import {
ObjectActionType,
setObjectEditTagsData,
setObjectOperation,
setupObjectVersion,
} from '@/store/slices/object';
import { getSpOffChainData } from '@/store/slices/persist';
import { SpEntity } from '@/store/slices/sp';
import { convertObjectKey } from '@/utils/common';
Expand All @@ -25,12 +30,30 @@ import { formatFullTime } from '@/utils/time';
import { VisibilityType } from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/common';
import { ResourceTags_Tag } from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/types';
import { ObjectMeta } from '@bnb-chain/greenfield-js-sdk/dist/esm/types/sp/Common';
import { Divider, Flex, QDrawerBody, QDrawerFooter, QDrawerHeader, Text } from '@node-real/uikit';
import { useUnmount } from 'ahooks';
import {
Divider,
Flex,
Loading,
QDrawerBody,
QDrawerFooter,
QDrawerHeader,
Tab,
TabList,
TabPanel,
TabPanels,
Tabs,
Text,
} from '@node-real/uikit';
import { useMount, useUnmount } from 'ahooks';
import { last } from 'lodash-es';
import { memo, useState } from 'react';
import { OBJECT_ERROR_TYPES, ObjectErrorType } from '../ObjectError';
import { setSignatureAction } from '@/store/slices/global';
import { ListEmpty } from '@/components/common/DCTable/ListEmpty';
import { TD, TH } from '@/modules/bucket/components/SPSelector/style';
import { VersionTable } from '@/modules/object/components/VersionTable';

const VERSION_TABS = ['General Info', 'Versions'];

interface DetailObjectOperationProps {
selectObjectInfo: ObjectMeta;
Expand All @@ -43,6 +66,7 @@ export const DetailObjectOperation = memo<DetailObjectOperationProps>(
function DetailOperation(props) {
const { selectObjectInfo, selectBucket, bucketAccountDetail, primarySp } = props;
const dispatch = useAppDispatch();
const objectVersionRecords = useAppSelector((root) => root.object.objectVersionRecords);
const accountRecords = useAppSelector((root) => root.persist.accountRecords);
const loginAccount = useAppSelector((root) => root.persist.loginAccount);
const currentBucketName = useAppSelector((root) => root.object.currentBucketName);
Expand All @@ -54,6 +78,9 @@ export const DetailObjectOperation = memo<DetailObjectOperationProps>(
const { directDownload: allowDirectDownload } = accountRecords?.[loginAccount] || {};
const objectInfo = selectObjectInfo.ObjectInfo;
const name = last(objectInfo.ObjectName.split('/'));
const versionKey = [currentBucketName, objectInfo.ObjectName].join('/');
const loading = !(versionKey in objectVersionRecords);
const objectVersions = objectVersionRecords[versionKey];

const errorHandler = (type: string) => {
setAction('');
Expand Down Expand Up @@ -121,6 +148,10 @@ export const DetailObjectOperation = memo<DetailObjectOperationProps>(
);
};

useMount(() => {
dispatch(setupObjectVersion(objectInfo.ObjectName, objectInfo.Id));
});

useUnmount(() => dispatch(setObjectEditTagsData([DEFAULT_TAG])));

return (
Expand Down Expand Up @@ -154,63 +185,78 @@ export const DetailObjectOperation = memo<DetailObjectOperationProps>(
</Text>
</Flex>
</Flex>
<Divider />
<Flex my={8} gap={8} flexDirection={'column'}>
{renderPropRow('Date created', formatFullTime(+objectInfo.CreateAt * 1000))}
{renderAddressLink(
'Object ID',
formatId(Number(objectInfo.Id)),
'dc.file.f_detail_pop.id.click',
'dc.file.f_detail_pop.copy_id.click',
'object',
)}
{renderAddressLink(
'Primary SP address',
primarySp.operatorAddress,
'dc.file.f_detail_pop.spadd.click',
'dc.file.f_detail_pop.copy_spadd.click',
)}
{renderAddressLink(
'Payment address',
selectBucket.PaymentAddress,
'dc.file.f_detail_pop.seal.click',
'dc.file.f_detail_pop.copy_seal.click',
)}
{renderAddressLink(
'Create transaction hash',
selectObjectInfo.CreateTxHash,
'dc.object.f_detail_pop.CreateTxHash.click',
'dc.object.f_detail_pop.copy_create_tx_hash.click',
'tx',
)}
{selectObjectInfo.SealTxHash !== EMPTY_TX_HASH &&
renderAddressLink(
'Seal transaction hash',
selectObjectInfo.SealTxHash,
'dc.object.f_detail_pop.SealTxHash.click',
'dc.object.f_detail_pop.copy_seal_tx_hash.click',
'tx',
)}
{objectInfo.Visibility === VisibilityType.VISIBILITY_TYPE_PUBLIC_READ &&
renderPropRow(
'Universal link',
renderUrlWithLink(
`${primarySp.endpoint}/view/${currentBucketName}/${encodeObjectName(
objectInfo.ObjectName,
)}`,
true,
32,
'dc.file.f_detail_pop.universal.click',
'dc.file.f_detail_pop.copy_universal.click',
),
)}
{renderTags({
onClick: onEditTags,
tagsCount: selectObjectInfo.ObjectInfo?.Tags.Tags.length || 0,
})}
</Flex>
<Divider />
<SharePermission selectObjectInfo={selectObjectInfo} />
<Tabs>
<TabList mb={24}>
{VERSION_TABS.map((tab) => (
<Tab h={24} key={tab} fontSize={14} fontWeight={500} pb={8}>
{tab}
</Tab>
))}
</TabList>
<TabPanels>
<TabPanel>
<Flex my={8} gap={8} flexDirection={'column'}>
{renderPropRow('Date created', formatFullTime(+objectInfo.CreateAt * 1000))}
{renderAddressLink(
'Object ID',
formatId(Number(objectInfo.Id)),
'dc.file.f_detail_pop.id.click',
'dc.file.f_detail_pop.copy_id.click',
'object',
)}
{renderAddressLink(
'Primary SP address',
primarySp.operatorAddress,
'dc.file.f_detail_pop.spadd.click',
'dc.file.f_detail_pop.copy_spadd.click',
)}
{renderAddressLink(
'Payment address',
selectBucket.PaymentAddress,
'dc.file.f_detail_pop.seal.click',
'dc.file.f_detail_pop.copy_seal.click',
)}
{renderAddressLink(
'Create transaction hash',
selectObjectInfo.CreateTxHash,
'dc.object.f_detail_pop.CreateTxHash.click',
'dc.object.f_detail_pop.copy_create_tx_hash.click',
'tx',
)}
{selectObjectInfo.SealTxHash !== EMPTY_TX_HASH &&
renderAddressLink(
'Seal transaction hash',
selectObjectInfo.SealTxHash,
'dc.object.f_detail_pop.SealTxHash.click',
'dc.object.f_detail_pop.copy_seal_tx_hash.click',
'tx',
)}
{objectInfo.Visibility === VisibilityType.VISIBILITY_TYPE_PUBLIC_READ &&
renderPropRow(
'Universal link',
renderUrlWithLink(
`${primarySp.endpoint}/view/${currentBucketName}/${encodeObjectName(
objectInfo.ObjectName,
)}`,
true,
32,
'dc.file.f_detail_pop.universal.click',
'dc.file.f_detail_pop.copy_universal.click',
),
)}
{renderTags({
onClick: onEditTags,
tagsCount: selectObjectInfo.ObjectInfo?.Tags.Tags.length || 0,
})}
</Flex>
<Divider />
<SharePermission selectObjectInfo={selectObjectInfo} />
</TabPanel>
<TabPanel>
<VersionTable loading={loading} versions={objectVersions} />
</TabPanel>
</TabPanels>
</Tabs>
</QDrawerBody>
{objectInfo.ObjectStatus === 1 && isBucketOwner && (
<QDrawerFooter flexDirection={'column'}>
Expand Down
Loading

0 comments on commit 6b5fffa

Please sign in to comment.