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(dcellar-web-ui): object version history support #378

Merged
merged 7 commits into from
Apr 29, 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: 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
Loading