Skip to content

Commit

Permalink
feat(dcellar-web-ui): introduce the migrate bucket feature (#379)
Browse files Browse the repository at this point in the history
* feat(dcellar-web-ui): introduce migrate bucket feature

* fix(dcellar-web-ui): delegateCreateFolder type error

* feat(dcellar-web-ui): add data update after migrate bucket

* feat(dcellar-web-ui): introduce activities feature for bucket, object… (#380)

* feat(dcellar-web-ui): introduce activities feature for bucket, object and group

* fix(dcellar-web-ui): text case error

* refactor(dcellar-web-ui): the transfer in style & toolbox style

* feat(dcellar-web-ui): add discord and release note link

* feat(dcellar-web-ui): introduce the stop upload feature (#385)

* feat(dcellar-web-ui): introduce the stop upload feature

* fix(dcellar-web-ui): the uploading name text ellispsis

* fix(dcellar-web-ui): change the stop status icon

* feat(dcellar-web-ui): introduce activities feature for bucket, object and group

* fix(dcellar-web-ui): text case error

* refactor(dcellar-web-ui): the transfer in style & toolbox style

* feat(dcellar-web-ui): add discord and release note link

* feat(dcellar-web-ui): introduce the stop upload feature

* refactor(dcellar-web-ui): remove rerandunt codes

* docs(dcellar-web-ui): update changelog

* feat(dcellar-web-ui): introduce migrate bucket feature

* chore(dcellar-web-ui): resolve build error

* docs(dcellar-web-ui): update changelog
  • Loading branch information
devinxl authored May 23, 2024
1 parent 64a220f commit 14b9b36
Show file tree
Hide file tree
Showing 26 changed files with 752 additions and 117 deletions.
15 changes: 15 additions & 0 deletions apps/dcellar-web-ui/CHANGELOG.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
{
"name": "dcellar-web-ui",
"entries": [
{
"version": "1.5.0",
"tag": "dcellar-web-ui_v1.5.0",
"date": "Thu, 23 May 2024 03:42:29 GMT",
"comments": {
"minor": [
{
"comment": "Support sponsor payment account"
},
{
"comment": "Introduce the migrate bucket feature"
}
]
}
},
{
"version": "1.4.0",
"tag": "dcellar-web-ui_v1.4.0",
Expand Down
10 changes: 9 additions & 1 deletion apps/dcellar-web-ui/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# Change Log - dcellar-web-ui

This log was last generated on Thu, 16 May 2024 09:14:19 GMT and should not be manually modified.
This log was last generated on Thu, 23 May 2024 03:42:29 GMT and should not be manually modified.

## 1.5.0
Thu, 23 May 2024 03:42:29 GMT

### Minor changes

- Support sponsor payment account
- Introduce the migrate bucket feature

## 1.4.0
Thu, 16 May 2024 09:14:19 GMT
Expand Down
4 changes: 2 additions & 2 deletions 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.4.0",
"version": "1.5.0",
"private": false,
"scripts": {
"dev": "node ./scripts/dev.js -p 3200",
Expand All @@ -19,7 +19,7 @@
"antd": "5.11.0",
"ahooks": "3.7.7",
"hash-wasm": "4.10.0",
"@bnb-chain/greenfield-js-sdk": "2.0.0-alpha.7",
"@bnb-chain/greenfield-js-sdk": "2.1.0-alpha.0",
"@bnb-chain/greenfield-cosmos-types": "0.4.0-alpha.32",
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@ import { Flex, Text } from '@node-real/uikit';
import NextLink from 'next/link';
import { useEffect, useState } from 'react';

export type InsufficientBalanceProps = {
export type InsufficientBalancesProps = {
loginAccount: string;
accounts: { address: string }[];
accounts: string[];
};

export const InsufficientBalance = ({ loginAccount, accounts }: InsufficientBalanceProps) => {
export const InsufficientBalances = ({ loginAccount, accounts }: InsufficientBalancesProps) => {
const [activeWays, setActiveWays] = useState<{ link: string; text: string }[]>([]);

useEffect(() => {
const ways = accounts.map((account) => {
const isOwnerAccount = account.address === loginAccount;
const isOwnerAccount = account === loginAccount;
return isOwnerAccount
? {
link: InternalRoutePaths.transfer_in,
text: 'Transfer in',
}
: {
link: `${InternalRoutePaths.send}&from=${loginAccount}&to=${account.address}`,
link: `${InternalRoutePaths.send}&from=${loginAccount}&to=${account}`,
text: 'Send',
};
});
Expand Down
9 changes: 8 additions & 1 deletion apps/dcellar-web-ui/src/components/layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface LayoutProps extends PropsWithChildren {}
export const Layout = memo<LayoutProps>(function Layout({ children }) {
const dispatch = useAppDispatch();
const isBucketDiscontinue = useAppSelector((root) => root.bucket.isBucketDiscontinue);
const isBucketMigrating = useAppSelector((root) => root.bucket.isBucketMigrating);
const isBucketOwner = useAppSelector((root) => root.bucket.isBucketOwner);
const bucketRecords = useAppSelector((root) => root.bucket.bucketRecords);
const currentBucketName = useAppSelector((root) => root.object.currentBucketName);
Expand Down Expand Up @@ -49,7 +50,13 @@ export const Layout = memo<LayoutProps>(function Layout({ children }) {
},
hover() {
if (pathname !== '/buckets/[...path]') return;
if (isBucketDiscontinue || !isBucketOwner || accountDetail.clientFrozen || !folderExist)
if (
isBucketDiscontinue ||
isBucketMigrating ||
!isBucketOwner ||
accountDetail.clientFrozen ||
!folderExist
)
return;
dispatch(setObjectOperation({ operation: ['', 'upload'] }));
},
Expand Down
29 changes: 28 additions & 1 deletion apps/dcellar-web-ui/src/facade/bucket.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { resolve } from '@/facade/common';
import { DeliverTxResponse, broadcastTx, resolve } from '@/facade/common';
import {
ErrorResponse,
broadcastFault,
Expand All @@ -18,6 +18,7 @@ import {
QueryQuoteUpdateTimeResponse,
} from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/query';
import {
MsgCancelMigrateBucket,
MsgCreateBucket,
MsgUpdateBucketInfo,
} from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/tx';
Expand All @@ -30,6 +31,7 @@ import {
IQuotaProps,
ISimulateGasFee,
Long,
MigrateBucketApprovalRequest,
ReadQuotaRequest,
SpResponse,
TxResponse,
Expand Down Expand Up @@ -456,3 +458,28 @@ export const getBucketActivities = async (id: string): Promise<Activity[]> => {

return result.data.result || [];
};

export const migrateBucket = async (
params: MigrateBucketApprovalRequest,
authType: AuthType,
connector: Connector,
): Promise<ErrorResponse | [DeliverTxResponse, null]> => {
const client = await getClient();
const [tx, error1] = await client.bucket
.migrateBucket(params, authType)
.then(resolve, createTxFault);
if (!tx) return [null, error1];

return broadcastTx({ tx: tx, address: params.operator, connector });
};

export const cancelMigrateBucket = async (
params: MsgCancelMigrateBucket,
connector: Connector,
): Promise<ErrorResponse | [DeliverTxResponse, null]> => {
const client = await getClient();
const [tx, error1] = await client.bucket.cancelMigrateBucket(params).then(resolve, createTxFault);
if (!tx) return [null, error1];

return broadcastTx({ tx: tx, address: params.operator, connector });
};
13 changes: 10 additions & 3 deletions apps/dcellar-web-ui/src/facade/object.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GROUP_ID } from '@/constants/legacy';
import { quotaRemains } from '@/facade/bucket';
import { getObjectInfoAndBucketQuota, resolve, resolveSpRequest } from '@/facade/common';
import { getObjectInfoAndBucketQuota, resolve } from '@/facade/common';
import {
E_NOT_FOUND,
E_NO_QUOTA,
Expand Down Expand Up @@ -41,6 +41,7 @@ import {
} from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/types';
import {
AuthType,
DelegateCreateFolderRepsonse,
DelegatedCreateFolderRequest,
GRNToString,
IQuotaProps,
Expand Down Expand Up @@ -713,8 +714,14 @@ export const updateObjectTags = async (params: UpdateObjectTagsParams, connector
export const delegateCreateFolder = async (
request: DelegatedCreateFolderRequest,
auth: AuthType,
) => {
): Promise<ErrorResponse | [DelegateCreateFolderRepsonse, null]> => {
const client = await getClient();
const [result, error] = await client.object
.delegateCreateFolder(request, auth)
.then(resolve, commonFault);

if (!result || error) return [null, error];
if (result.code !== 0 || !result.body) return [null, result.message ?? ''];

return client.object.delegateCreateFolder(request, auth).then(resolveSpRequest, commonFault);
return [result.body, null];
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import { setObjectListPage } from '@/store/slices/object';
import { formatFullTime } from '@/utils/time';
import styled from '@emotion/styled';
import Link from 'next/link';
import { memo } from 'react';
import { DiscontinueNotice } from './DiscontinueNotice';
import { memo, useMemo } from 'react';
import { BucketStatus as BucketStatusEnum } from '@bnb-chain/greenfield-js-sdk';
import { BucketStatusNotice } from './BucketStatusNotice';

interface BucketNameColumnProps {
item: BucketEntity;
Expand All @@ -16,14 +17,33 @@ export const BucketNameColumn = memo<BucketNameColumnProps>(function BucketNameC
const dispatch = useAppDispatch();
const bucketRecords = useAppSelector((root) => root.bucket.bucketRecords);
const { DeleteAt, BucketStatus, BucketName, OffChainStatus } = bucketRecords[item.BucketName];
const discontinue = BucketStatus === 1;
const estimateTime = formatFullTime(
+DeleteAt * 1000 + 7 * 24 * 60 * 60 * 1000,
'YYYY-MM-DD HH:mm:ss',
);
const more = 'https://docs.nodereal.io/docs/dcellar-faq#question-what-is-discontinue';
const content = `This item will be deleted by SP with an estimated time of ${estimateTime}. Please backup your data in time.`;
const isFlowRateLimit = ['1', '3'].includes(OffChainStatus);
const bucketStatusReason = useMemo(() => {
switch (BucketStatus) {
case BucketStatusEnum.BUCKET_STATUS_DISCONTINUED: {
const estimateTime = formatFullTime(
+DeleteAt * 1000 + 7 * 24 * 60 * 60 * 1000,
'YYYY-MM-DD HH:mm:ss',
);
return {
icon: 'colored-error2',
title: 'Discontinue Notice',
link: 'https://docs.nodereal.io/docs/dcellar-faq#question-what-is-discontinue',
desc: `This item will be deleted by SP with an estimated time of ${estimateTime}. Please backup your data in time.`,
show: true,
};
}
case BucketStatusEnum.BUCKET_STATUS_MIGRATING:
return {
icon: 'migrate',
title: 'Data Migrating',
desc: 'This bucket, in the process of data migration to another provider, supports only downloads, quota modifications, deletions, and sharing. It does not support uploads.',
show: true,
};
default:
return null;
}
}, [BucketStatus, DeleteAt]);

return (
<Container>
Expand All @@ -37,12 +57,10 @@ export const BucketNameColumn = memo<BucketNameColumnProps>(function BucketNameC
<IconFont type="bucket-thumbnail" w={20} />
<span title={item.BucketName}>{item.BucketName}</span>
</Link>
{(discontinue || isFlowRateLimit) && (
<DiscontinueNotice
discontinue={discontinue}
{(bucketStatusReason || isFlowRateLimit) && (
<BucketStatusNotice
bucketStatusReason={bucketStatusReason}
flowRateLimit={isFlowRateLimit}
content={content}
learnMore={more}
/>
)}
</Container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { EditBucketTagsOperation } from './EditBucketTagsOperation';
import { PaymentAccountOperation } from './PaymentAccountOperation';
import { UpdateBucketTagsOperation } from './UpdateBucketTagsOperation';
import { useRouter } from 'next/router';
import { MigrateBucketOperation } from './MigrateBucketOperation';

interface BucketOperationsProps {
level?: 0 | 1;
Expand All @@ -41,6 +42,7 @@ export const BucketOperations = memo<BucketOperationsProps>(function BucketOpera
'tags',
'edit_tags',
'update_tags',
'migrate',
].includes(operation);
const isModal = ['delete'].includes(operation);
const _operation = useModalValues<BucketOperationsType>(operation);
Expand Down Expand Up @@ -78,6 +80,8 @@ export const BucketOperations = memo<BucketOperationsProps>(function BucketOpera
return <EditBucketTagsOperation onClose={onClose} />;
case 'update_tags':
return <UpdateBucketTagsOperation bucket={_selectBucketInfo} onClose={onClose} />;
case 'migrate':
return <MigrateBucketOperation bucket={_selectBucketInfo} onClose={onClose} />;
default:
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,36 @@ import { IconFont } from '@/components/IconFont';
import { DCLink } from '@/components/common/DCLink';
import { Box, Divider, Flex, Menu, MenuButton, MenuList, Text } from '@node-real/uikit';

export const DiscontinueNotice = ({
content,
learnMore,
type InvalidStatusReason = {
title: string;
desc: string;
link?: string;
icon: string;
show: boolean;
};
export const BucketStatusNotice = ({
flowRateLimit = false,
discontinue = true,
bucketStatusReason,
}: {
content: string;
learnMore: string;
flowRateLimit?: boolean;
discontinue?: boolean;
bucketStatusReason: {
title: string;
desc: string;
link?: string;
icon: string;
show: boolean;
} | null;
}) => {
const account = discontinue && flowRateLimit ? 2 : 0;
const discontinueReasons = [
const account = bucketStatusReason && flowRateLimit ? 2 : 0;
const discontinueReasons: InvalidStatusReason[] = [
{
icon: 'colored-error2',
title: 'Flow rate exceeds limit',
desc: "The bucket's flow rate exceeds the payment account limit. Contact the account owner or switch accounts to increase it.",
link: 'https://docs.nodereal.io/docs/dcellar-faq#question-why-is-my-bucket-flow-rate-limited',
show: flowRateLimit,
},
{ title: 'Discontinue Notice', desc: content, link: learnMore, show: discontinue },
bucketStatusReason || { title: '', desc: '', icon: '', show: false },
].filter((i) => i.show);

return (
Expand All @@ -35,7 +45,14 @@ export const DiscontinueNotice = ({
alignItems={'center'}
fontWeight={600}
>
<IconFont type="colored-error2" w={16} />
<IconFont
type={
flowRateLimit
? 'colored-error2'
: (bucketStatusReason && bucketStatusReason.icon) || 'colored-error2'
}
w={16}
/>
{!!account && <>{account}</>}
</MenuButton>
<MenuList>
Expand All @@ -48,9 +65,11 @@ export const DiscontinueNotice = ({
</Text>
<Text color={'readable.secondary'}>{desc}</Text>
<Flex justifyContent={'right'}>
<DCLink href={link} target="_blank" onClick={(e) => e.stopPropagation()}>
Learn More
</DCLink>
{link && (
<DCLink href={link} target="_blank" onClick={(e) => e.stopPropagation()}>
Learn More
</DCLink>
)}
</Flex>
{index !== discontinueReasons.length - 1 && <Divider my={12} />}
</Box>
Expand Down
Loading

0 comments on commit 14b9b36

Please sign in to comment.