From e96cdcaab286f50b17a6a3e062a3e80e64962eac Mon Sep 17 00:00:00 2001 From: aidencao Date: Sun, 7 Apr 2024 17:14:48 +0800 Subject: [PATCH 1/3] feat(dcellar-web-ui): created on chain status deletable --- .../src/components/common/DCTable/index.tsx | 2 +- apps/dcellar-web-ui/src/facade/account.ts | 4 +- .../components/BatchDeleteObjectOperation.tsx | 29 +++++++++++++-- .../modules/object/components/ObjectList.tsx | 37 +++++++++++++------ .../modules/upload/UploadObjectsOperation.tsx | 2 +- 5 files changed, 54 insertions(+), 20 deletions(-) diff --git a/apps/dcellar-web-ui/src/components/common/DCTable/index.tsx b/apps/dcellar-web-ui/src/components/common/DCTable/index.tsx index 06b449f5..8c6e16f8 100644 --- a/apps/dcellar-web-ui/src/components/common/DCTable/index.tsx +++ b/apps/dcellar-web-ui/src/components/common/DCTable/index.tsx @@ -176,7 +176,7 @@ export const UploadStatus = ({ object, size }: { object: string; size: number }) ] .filter((item) => !!item) .join('/'); - return objectInList === object; + return objectInList === object && q.status !== 'ERROR'; }); if (!file) return Created on Chain; diff --git a/apps/dcellar-web-ui/src/facade/account.ts b/apps/dcellar-web-ui/src/facade/account.ts index 128bf779..a4a961ab 100644 --- a/apps/dcellar-web-ui/src/facade/account.ts +++ b/apps/dcellar-web-ui/src/facade/account.ts @@ -41,7 +41,7 @@ export const getAccountBalance = async ({ export type CreateTmpAccountParams = { address: string; bucketName: string; - amount: number; + amount: ReturnType; connector: Connector; actionType?: 'delete' | 'create'; }; @@ -74,7 +74,7 @@ export const createTempAccount = async ({ granter: address, grantee: wallet.address, allowedMessages: grantAllowedMessage, - amount: parseEther(amount <= 0 ? '0.1' : String(amount)).toString(), + amount: parseEther(amount.lte(0) ? '0.1' : String(amount)).toString(), denom: 'BNB', expirationTime: toTimestamp(expirationDate), }) diff --git a/apps/dcellar-web-ui/src/modules/object/components/BatchDeleteObjectOperation.tsx b/apps/dcellar-web-ui/src/modules/object/components/BatchDeleteObjectOperation.tsx index 38a8dfa4..bcacc3c1 100644 --- a/apps/dcellar-web-ui/src/modules/object/components/BatchDeleteObjectOperation.tsx +++ b/apps/dcellar-web-ui/src/modules/object/components/BatchDeleteObjectOperation.tsx @@ -19,7 +19,12 @@ import { setupAccountRecords, } from '@/store/slices/accounts'; import { TBucket } from '@/store/slices/bucket'; -import { selectGnfdGasFeesConfig, setSignatureAction } from '@/store/slices/global'; +import { + selectGnfdGasFeesConfig, + selectUploadQueue, + setSignatureAction, + UploadObject, +} from '@/store/slices/global'; import { setDeletedObject, setObjectSelectedKeys } from '@/store/slices/object'; import { BN } from '@/utils/math'; import { getStoreNetflowRate } from '@/utils/payment'; @@ -34,7 +39,7 @@ import { ColoredWaitingIcon } from '@node-real/icons'; import { Flex, ModalBody, ModalFooter, ModalHeader, Text, toast } from '@node-real/uikit'; import { useAsyncEffect } from 'ahooks'; import { parseEther } from 'ethers/lib/utils.js'; -import { round } from 'lodash-es'; +import { find, round } from 'lodash-es'; import { memo, useMemo, useState } from 'react'; import { useAccount } from 'wagmi'; @@ -60,6 +65,7 @@ export const BatchDeleteObjectOperation = memo( const bankBalance = useAppSelector((root) => root.accounts.bankOrWalletBalance); const gnfdGasFeesConfig = useAppSelector(selectGnfdGasFeesConfig); + const uploadQueue = useAppSelector(selectUploadQueue(loginAccount)); const { crudTimestamp } = useAppSelector(selectAccount(bucket?.PaymentAddress)); const availableBalance = useAppSelector(selectAvailableBalance(bucket?.PaymentAddress)); const [loading, setLoading] = useState(false); @@ -126,10 +132,12 @@ export const BatchDeleteObjectOperation = memo( desc: WALLET_CONFIRM, }), ); + const [tempAccount, err] = await createTempAccount({ address: loginAccount, bucketName: currentBucketName, - amount: parseEther(round(Number(availableBalance), 6).toString()).toNumber(), + // fix toNumber overflow fault + amount: parseEther(round(Number(availableBalance), 6).toString()), connector: connector!, actionType: 'delete', }); @@ -149,7 +157,20 @@ export const BatchDeleteObjectOperation = memo( connector: connector!, privateKey, }; - const [txRes, error] = await (ObjectStatus === 1 + + const file = find(uploadQueue, (q) => { + const objectInList = [ + ...q.prefixFolders, + q.waitObject.relativePath || '', + q.waitObject.name, + ] + .filter((item) => !!item) + .join('/'); + + return objectInList === objectName && q.status !== 'ERROR'; + }); + + const [txRes, error] = await (ObjectStatus === 1 || (ObjectStatus !== 1 && !file) ? deleteObject(payload) : cancelCreateObject(payload)); if (error && error !== E_OBJECT_NOT_EXISTS) { diff --git a/apps/dcellar-web-ui/src/modules/object/components/ObjectList.tsx b/apps/dcellar-web-ui/src/modules/object/components/ObjectList.tsx index 6082ac5d..1becbc93 100644 --- a/apps/dcellar-web-ui/src/modules/object/components/ObjectList.tsx +++ b/apps/dcellar-web-ui/src/modules/object/components/ObjectList.tsx @@ -58,7 +58,6 @@ import { find, uniq, without, xor } from 'lodash-es'; import { memo, useCallback } from 'react'; import { OBJECT_ERROR_TYPES, ObjectErrorType } from '../ObjectError'; import Link from 'next/link'; -// import { ManageObjectTagsDrawer } from './ManageObjectTagsDrawer'; export type ObjectActionValueType = | 'marketplace' @@ -348,17 +347,18 @@ export const ObjectList = memo(function ObjectList({ shareMode const file = find( uploadQueue, (q) => - [...q.prefixFolders, q.waitObject.name].join('/') === record.objectName && - q.status !== 'ERROR', + [...q.prefixFolders, q.waitObject.relativePath || '', q.waitObject.name] + .filter((item) => !!item) + .join('/') === record.objectName && q.status !== 'ERROR', ); // if is uploading, can not cancel; if (file && ['SIGN', 'SIGNED', 'UPLOAD'].includes(file.status)) { pruneActions = pickAction(pruneActions, ['detail']); - } else if (file && ['SEAL'].includes(file.status)) { - pruneActions = removeAction(pruneActions, ['cancel', 'share']); + } else if (file && ['SEAL', 'SEALING'].includes(file.status)) { + pruneActions = removeAction(pruneActions, ['cancel', 'share', 'delete']); } else { // if not sealed, only support 'cancel' 'detail' - pruneActions = pickAction(pruneActions, ['cancel', 'detail']); + pruneActions = pickAction(pruneActions, ['detail', 'delete']); } } @@ -402,10 +402,25 @@ export const ObjectList = memo(function ObjectList({ shareMode selectedRowKeys: objectSelectedKeys, onSelect: onSelectChange, onSelectAll: onSelectAllChange, - getCheckboxProps: (record: ObjectEntity) => ({ - disabled: record.folder || record.objectStatus !== 1, // Column configuration not to be checked - name: record.name, - }), + getCheckboxProps: (record: ObjectEntity) => { + const file = find(uploadQueue, (q) => { + const objectInList = [ + ...q.prefixFolders, + q.waitObject.relativePath || '', + q.waitObject.name, + ] + .filter((item) => !!item) + .join('/'); + + return objectInList === record.objectName && q.status !== 'ERROR'; + }); + + return { + // folder or upload failed + disabled: record.folder || (record.objectStatus !== 1 && !!file), // Column configuration not to be checked + name: record.name, + }; + }, }; const errorHandler = (type: string) => { @@ -464,8 +479,6 @@ export const ObjectList = memo(function ObjectList({ shareMode address: loginAccount, }; - // const operator = primarySpInfo.operatorAddress; - // const { seedString } = await dispatch(getSpOffChainData(loginAccount, operator)); const [success, opsError] = await downloadObject(params, seedString); if (opsError) return errorHandler(opsError); dispatch(setupBucketQuota(currentBucketName)); diff --git a/apps/dcellar-web-ui/src/modules/upload/UploadObjectsOperation.tsx b/apps/dcellar-web-ui/src/modules/upload/UploadObjectsOperation.tsx index 92f5fc7d..2d9cd24b 100644 --- a/apps/dcellar-web-ui/src/modules/upload/UploadObjectsOperation.tsx +++ b/apps/dcellar-web-ui/src/modules/upload/UploadObjectsOperation.tsx @@ -336,7 +336,7 @@ export const UploadObjectsOperation = memo( const [tempAccount, error] = await createTempAccount({ address: loginAccount, bucketName: currentBucketName, - amount: parseEther(String(safeAmount)).toNumber(), + amount: parseEther(String(safeAmount)), connector: connector!, }); if (!tempAccount) { From 2a05d4e9c4cfabf5ea47651dce8f32640c375d79 Mon Sep 17 00:00:00 2001 From: aidencao Date: Tue, 9 Apr 2024 10:56:40 +0800 Subject: [PATCH 2/3] feat(dcellar-web-ui): remove some duplicate code --- .../src/components/common/DCTable/index.tsx | 27 +++++--------- .../src/hooks/useUploadProcessObjects.ts | 30 ++++++++++++++++ .../components/BatchDeleteObjectOperation.tsx | 20 +++-------- .../modules/object/components/ObjectList.tsx | 35 +++++++------------ 4 files changed, 56 insertions(+), 56 deletions(-) create mode 100644 apps/dcellar-web-ui/src/hooks/useUploadProcessObjects.ts diff --git a/apps/dcellar-web-ui/src/components/common/DCTable/index.tsx b/apps/dcellar-web-ui/src/components/common/DCTable/index.tsx index 8c6e16f8..fb1e4dc2 100644 --- a/apps/dcellar-web-ui/src/components/common/DCTable/index.tsx +++ b/apps/dcellar-web-ui/src/components/common/DCTable/index.tsx @@ -5,14 +5,13 @@ import { SimplePaginationProps, } from '@/components/common/DCTable/SimplePagination'; import { useAppSelector } from '@/store'; -import { UploadObject, selectUploadQueue } from '@/store/slices/global'; import { formatBytes } from '@/utils/formatter'; import styled from '@emotion/styled'; -import { Badge, Box, Flex, Pagination, PaginationProps, Text, keyframes } from '@node-real/uikit'; +import { Badge, Box, Flex, keyframes, Pagination, PaginationProps, Text } from '@node-real/uikit'; import { ConfigProvider, Table, TableProps } from 'antd'; import { ConfigProviderProps } from 'antd/es/config-provider'; -import { find } from 'lodash-es'; import { memo } from 'react'; +import { useUploadProcessObjects } from '@/hooks/useUploadProcessObjects'; export type AlignType = 'left' | 'right' | 'center'; @@ -165,21 +164,13 @@ export const UploadProgress = (props: { progress: number }) => { export const UploadStatus = ({ object, size }: { object: string; size: number }) => { const loginAccount = useAppSelector((root) => root.persist.loginAccount); - const queue = useAppSelector(selectUploadQueue(loginAccount)); - - const file = find(queue, (q) => { - const objectInList = [ - q.bucketName, - ...q.prefixFolders, - q.waitObject.relativePath || '', - q.waitObject.name, - ] - .filter((item) => !!item) - .join('/'); - return objectInList === object && q.status !== 'ERROR'; - }); - - if (!file) return Created on Chain; + const { processUploadObjects, processUploadObjectRecord } = useUploadProcessObjects(loginAccount); + + const processing = processUploadObjects.includes(object); + + if (!processing) return Created on Chain; + + const file = processUploadObjectRecord[object]; if (file.status === 'UPLOAD') return ; diff --git a/apps/dcellar-web-ui/src/hooks/useUploadProcessObjects.ts b/apps/dcellar-web-ui/src/hooks/useUploadProcessObjects.ts new file mode 100644 index 00000000..9367cb08 --- /dev/null +++ b/apps/dcellar-web-ui/src/hooks/useUploadProcessObjects.ts @@ -0,0 +1,30 @@ +import { useAppSelector } from '@/store'; +import { selectUploadQueue, UploadObject } from '@/store/slices/global'; +import { useMemo } from 'react'; + +export const useUploadProcessObjects = (loginAccount: string) => { + const queue = useAppSelector(selectUploadQueue(loginAccount)); + + return useMemo(() => { + const processUploadObjectRecord: Record = {}; + const processUploadObjects = queue + .filter((q) => q.status !== 'ERROR') + .map((q) => { + const key = [ + q.bucketName, + ...q.prefixFolders, + q.waitObject.relativePath || '', + q.waitObject.name, + ] + .filter((item) => !!item) + .join('/'); + processUploadObjectRecord[key] = q; + return key; + }); + + return { + processUploadObjects, + processUploadObjectRecord, + }; + }, [queue]); +}; diff --git a/apps/dcellar-web-ui/src/modules/object/components/BatchDeleteObjectOperation.tsx b/apps/dcellar-web-ui/src/modules/object/components/BatchDeleteObjectOperation.tsx index bcacc3c1..b34cbb97 100644 --- a/apps/dcellar-web-ui/src/modules/object/components/BatchDeleteObjectOperation.tsx +++ b/apps/dcellar-web-ui/src/modules/object/components/BatchDeleteObjectOperation.tsx @@ -23,7 +23,6 @@ import { selectGnfdGasFeesConfig, selectUploadQueue, setSignatureAction, - UploadObject, } from '@/store/slices/global'; import { setDeletedObject, setObjectSelectedKeys } from '@/store/slices/object'; import { BN } from '@/utils/math'; @@ -39,9 +38,10 @@ import { ColoredWaitingIcon } from '@node-real/icons'; import { Flex, ModalBody, ModalFooter, ModalHeader, Text, toast } from '@node-real/uikit'; import { useAsyncEffect } from 'ahooks'; import { parseEther } from 'ethers/lib/utils.js'; -import { find, round } from 'lodash-es'; +import { round } from 'lodash-es'; import { memo, useMemo, useState } from 'react'; import { useAccount } from 'wagmi'; +import { useUploadProcessObjects } from '@/hooks/useUploadProcessObjects'; interface BatchDeleteObjectOperationProps { selectBucket: TBucket; @@ -65,7 +65,6 @@ export const BatchDeleteObjectOperation = memo( const bankBalance = useAppSelector((root) => root.accounts.bankOrWalletBalance); const gnfdGasFeesConfig = useAppSelector(selectGnfdGasFeesConfig); - const uploadQueue = useAppSelector(selectUploadQueue(loginAccount)); const { crudTimestamp } = useAppSelector(selectAccount(bucket?.PaymentAddress)); const availableBalance = useAppSelector(selectAvailableBalance(bucket?.PaymentAddress)); const [loading, setLoading] = useState(false); @@ -76,6 +75,7 @@ export const BatchDeleteObjectOperation = memo( const { loading: loadingSettlementFee, settlementFee } = useSettlementFee( bucket?.PaymentAddress, ); + const { processUploadObjects } = useUploadProcessObjects(loginAccount); const deleteObjects = objectSelectedKeys.map((key) => { return objectRecords[currentBucketName + '/' + key]; @@ -158,19 +158,9 @@ export const BatchDeleteObjectOperation = memo( privateKey, }; - const file = find(uploadQueue, (q) => { - const objectInList = [ - ...q.prefixFolders, - q.waitObject.relativePath || '', - q.waitObject.name, - ] - .filter((item) => !!item) - .join('/'); + const processing = processUploadObjects.includes(`${currentBucketName}/${objectName}`); - return objectInList === objectName && q.status !== 'ERROR'; - }); - - const [txRes, error] = await (ObjectStatus === 1 || (ObjectStatus !== 1 && !file) + const [txRes, error] = await (ObjectStatus === 1 || (ObjectStatus !== 1 && !processing) ? deleteObject(payload) : cancelCreateObject(payload)); if (error && error !== E_OBJECT_NOT_EXISTS) { diff --git a/apps/dcellar-web-ui/src/modules/object/components/ObjectList.tsx b/apps/dcellar-web-ui/src/modules/object/components/ObjectList.tsx index 1becbc93..1d6747ae 100644 --- a/apps/dcellar-web-ui/src/modules/object/components/ObjectList.tsx +++ b/apps/dcellar-web-ui/src/modules/object/components/ObjectList.tsx @@ -54,10 +54,11 @@ import { Box, Flex } from '@node-real/uikit'; import { useAsyncEffect, useUpdateEffect } from 'ahooks'; import { ColumnProps } from 'antd/es/table'; import dayjs from 'dayjs'; -import { find, uniq, without, xor } from 'lodash-es'; +import { uniq, without, xor } from 'lodash-es'; import { memo, useCallback } from 'react'; import { OBJECT_ERROR_TYPES, ObjectErrorType } from '../ObjectError'; import Link from 'next/link'; +import { useUploadProcessObjects } from '@/hooks/useUploadProcessObjects'; export type ObjectActionValueType = | 'marketplace' @@ -122,6 +123,7 @@ export const ObjectList = memo(function ObjectList({ shareMode const loading = useAppSelector(selectPathLoading); const objectList = useAppSelector(selectObjectList); const uploadQueue = useAppSelector(selectUploadQueue(loginAccount)); + const { processUploadObjects, processUploadObjectRecord } = useUploadProcessObjects(loginAccount); const { setOpenAuthModal } = useOffChainAuth(); const bucket = bucketRecords[currentBucketName]; @@ -344,17 +346,13 @@ export const ObjectList = memo(function ObjectList({ shareMode pruneActions = removeAction(pruneActions, ['cancel']); } else { // It is not allowed to cancel when the chain is sealed, but the SP is not synchronized. - const file = find( - uploadQueue, - (q) => - [...q.prefixFolders, q.waitObject.relativePath || '', q.waitObject.name] - .filter((item) => !!item) - .join('/') === record.objectName && q.status !== 'ERROR', - ); + const object = `${record.bucketName}/${record.objectName}`; + const processing = processUploadObjects.includes(object); + const file = processUploadObjectRecord[object]; // if is uploading, can not cancel; - if (file && ['SIGN', 'SIGNED', 'UPLOAD'].includes(file.status)) { + if (processing && ['SIGN', 'SIGNED', 'UPLOAD'].includes(file.status)) { pruneActions = pickAction(pruneActions, ['detail']); - } else if (file && ['SEAL', 'SEALING'].includes(file.status)) { + } else if (processing && ['SEAL', 'SEALING'].includes(file.status)) { pruneActions = removeAction(pruneActions, ['cancel', 'share', 'delete']); } else { // if not sealed, only support 'cancel' 'detail' @@ -403,21 +401,12 @@ export const ObjectList = memo(function ObjectList({ shareMode onSelect: onSelectChange, onSelectAll: onSelectAllChange, getCheckboxProps: (record: ObjectEntity) => { - const file = find(uploadQueue, (q) => { - const objectInList = [ - ...q.prefixFolders, - q.waitObject.relativePath || '', - q.waitObject.name, - ] - .filter((item) => !!item) - .join('/'); - - return objectInList === record.objectName && q.status !== 'ERROR'; - }); + const object = `${record.bucketName}/${record.objectName}`; + const processing = processUploadObjects.includes(object); return { - // folder or upload failed - disabled: record.folder || (record.objectStatus !== 1 && !!file), // Column configuration not to be checked + // folder or processing + disabled: record.folder || (record.objectStatus !== 1 && processing), // Column configuration not to be checked name: record.name, }; }, From ac524891bbf1df54cf54fffdfde5fc8b7744276b Mon Sep 17 00:00:00 2001 From: aidencao Date: Thu, 11 Apr 2024 10:30:31 +0800 Subject: [PATCH 3/3] chore(dcellar-web-ui): update changelog --- apps/dcellar-web-ui/CHANGELOG.json | 12 ++++++++++++ apps/dcellar-web-ui/CHANGELOG.md | 9 ++++++++- apps/dcellar-web-ui/package.json | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/apps/dcellar-web-ui/CHANGELOG.json b/apps/dcellar-web-ui/CHANGELOG.json index fae71c3d..ab7475be 100644 --- a/apps/dcellar-web-ui/CHANGELOG.json +++ b/apps/dcellar-web-ui/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "dcellar-web-ui", "entries": [ + { + "version": "0.5.0", + "tag": "dcellar-web-ui_v0.5.0", + "date": "Thu, 11 Apr 2024 02:29:47 GMT", + "comments": { + "minor": [ + { + "comment": "make created on chain status object deletable" + } + ] + } + }, { "version": "0.4.0", "tag": "dcellar-web-ui_v0.4.0", diff --git a/apps/dcellar-web-ui/CHANGELOG.md b/apps/dcellar-web-ui/CHANGELOG.md index 6360cf5c..c2f1caf3 100644 --- a/apps/dcellar-web-ui/CHANGELOG.md +++ b/apps/dcellar-web-ui/CHANGELOG.md @@ -1,6 +1,13 @@ # Change Log - dcellar-web-ui -This log was last generated on Mon, 25 Mar 2024 04:02:13 GMT and should not be manually modified. +This log was last generated on Thu, 11 Apr 2024 02:29:47 GMT and should not be manually modified. + +## 0.5.0 +Thu, 11 Apr 2024 02:29:47 GMT + +### Minor changes + +- make created on chain status object deletable ## 0.4.0 Mon, 25 Mar 2024 04:02:13 GMT diff --git a/apps/dcellar-web-ui/package.json b/apps/dcellar-web-ui/package.json index 7728b3d8..24c4bcf7 100644 --- a/apps/dcellar-web-ui/package.json +++ b/apps/dcellar-web-ui/package.json @@ -1,6 +1,6 @@ { "name": "dcellar-web-ui", - "version": "0.4.0", + "version": "0.5.0", "private": false, "scripts": { "dev": "node ./scripts/dev.js -p 3200",