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", 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..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; - }); - - 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/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/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 38a8dfa4..b34cbb97 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,11 @@ import { setupAccountRecords, } from '@/store/slices/accounts'; import { TBucket } from '@/store/slices/bucket'; -import { selectGnfdGasFeesConfig, setSignatureAction } from '@/store/slices/global'; +import { + selectGnfdGasFeesConfig, + selectUploadQueue, + setSignatureAction, +} from '@/store/slices/global'; import { setDeletedObject, setObjectSelectedKeys } from '@/store/slices/object'; import { BN } from '@/utils/math'; import { getStoreNetflowRate } from '@/utils/payment'; @@ -37,6 +41,7 @@ import { parseEther } from 'ethers/lib/utils.js'; import { round } from 'lodash-es'; import { memo, useMemo, useState } from 'react'; import { useAccount } from 'wagmi'; +import { useUploadProcessObjects } from '@/hooks/useUploadProcessObjects'; interface BatchDeleteObjectOperationProps { selectBucket: TBucket; @@ -70,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]; @@ -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,10 @@ export const BatchDeleteObjectOperation = memo( connector: connector!, privateKey, }; - const [txRes, error] = await (ObjectStatus === 1 + + const processing = processUploadObjects.includes(`${currentBucketName}/${objectName}`); + + 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 6082ac5d..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,11 +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 { ManageObjectTagsDrawer } from './ManageObjectTagsDrawer'; +import { useUploadProcessObjects } from '@/hooks/useUploadProcessObjects'; export type ObjectActionValueType = | 'marketplace' @@ -123,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]; @@ -345,20 +346,17 @@ 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.name].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'].includes(file.status)) { - pruneActions = removeAction(pruneActions, ['cancel', 'share']); + } else if (processing && ['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 +400,16 @@ 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 object = `${record.bucketName}/${record.objectName}`; + const processing = processUploadObjects.includes(object); + + return { + // folder or processing + disabled: record.folder || (record.objectStatus !== 1 && processing), // Column configuration not to be checked + name: record.name, + }; + }, }; const errorHandler = (type: string) => { @@ -464,8 +468,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) {