Skip to content

Commit

Permalink
feat(dcellar-web-ui): introduce the stop upload feature (#385)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
devinxl authored May 16, 2024
1 parent f4a3e98 commit af91da1
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 64 deletions.
1 change: 1 addition & 0 deletions apps/dcellar-web-ui/public/js/iconfont_v0.1.12.min.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ export const GlobalObjectUploadManager = memo<GlobalTasksProps>(
} else {
axios
.put(url, task.waitObject.file, {
signal: task.abortController?.signal,
async onUploadProgress(progressEvent) {
const progress = progressEvent.total
? Math.floor((progressEvent.loaded / progressEvent.total) * 100)
Expand Down Expand Up @@ -265,6 +266,7 @@ export const GlobalObjectUploadManager = memo<GlobalTasksProps>(
setupUploadTaskErrorMsg({
account: loginAccount,
task,
status: e?.code === 'ERR_CANCELED' ? 'CANCEL' : 'ERROR',
errorMsg: authExpired
? 'Authentication expired.'
: message || e?.message || 'upload error',
Expand Down Expand Up @@ -461,8 +463,28 @@ export const GlobalObjectUploadManager = memo<GlobalTasksProps>(
// 3. upload
useAsyncEffect(async () => {
if (!uploadTasks.length) return;
dispatch(updateUploadStatus({ ids: uploadTasks, status: 'UPLOAD', account: loginAccount }));
const tasks = queue.filter((t) => uploadTasks.includes(t.id));
// Add abortController to each task
const extraFields: Record<string, Partial<UploadObject>> = uploadTasks.reduce(
(acc, id) => {
acc[id] = {
abortController: new AbortController(),
};
return acc;
},
{} as Record<string, Partial<UploadObject>>,
);
dispatch(
updateUploadStatus({
ids: uploadTasks,
status: 'UPLOAD',
account: loginAccount,
extraFields,
}),
);

const tasks = queue
.filter((t) => uploadTasks.includes(t.id))
.map((t) => ({ ...t, ...extraFields[t.id] }));
tasks.forEach(runUploadTask);
}, [uploadTasks.join('')]);

Expand Down
14 changes: 9 additions & 5 deletions apps/dcellar-web-ui/src/modules/upload/ObjectUploadStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { UploadObject } from '@/store/slices/global';
import { Text } from '@node-real/uikit';
import { Loading } from '@/components/common/Loading';
import { UploadProgress } from './UploadProgress';
import { IconFont } from '@/components/IconFont';
import { memo } from 'react';

export const ObjectUploadStatus = ({ task }: { task: UploadObject }) => {
export const ObjectUploadStatus = memo(function ObjectUploadStatus({
task,
}: {
task: UploadObject;
}) {
switch (task.status) {
case 'RETRY_CHECK':
case 'RETRY_CHECKING':
Expand Down Expand Up @@ -61,11 +65,11 @@ export const ObjectUploadStatus = ({ task }: { task: UploadObject }) => {
case 'CANCEL':
return (
<>
<IconFont type="colored-error2" w={20} />
Cancelled
<IconFont type="stop" w={20} />
Stopped
</>
);
default:
return null;
}
};
});
65 changes: 52 additions & 13 deletions apps/dcellar-web-ui/src/modules/upload/UploadActionButton.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,58 @@
import { IconFont } from '@/components/IconFont';
import { DCButton } from '@/components/common/DCButton';
import { useAppDispatch, useAppSelector } from '@/store';
import { clearUploadRecords, retryUploadTasks } from '@/store/slices/global';
import {
cancelUploadingRequests,
clearUploadRecords,
retryUploadTasks,
updateUploadStatus,
} from '@/store/slices/global';
<<<<<<< HEAD
<<<<<<< HEAD
import React, { useCallback } from 'react';
=======
=======
>>>>>>> f143b09b (feat(dcellar-web-ui): introduce the stop upload feature)
import React from 'react';
>>>>>>> 2ee2f675 (feat(dcellar-web-ui): introduce the stop upload feature)

export type ActionButtonProps = {
type: 'clear' | 'retry' | 'clear-all' | 'retry-all';
type: 'clear' | 'retry' | 'clear-all' | 'retry-all' | 'cancel' | 'cancel-all';
ids: number[];
text?: string;
};

const actionItems = [
{
type: 'clear',
text: 'Clear',
icon: 'delete',
type: 'cancel',
text: 'Cancel',
icon: 'stop',
},
{
type: 'cancel-all',
text: 'Stop Uploading',
icon: 'stop',
},
{
type: 'retry',
text: 'Retry',
icon: 'retry',
},
{
type: 'clear-all',
text: 'Clear All Records',
icon: 'delete',
},
{
type: 'retry-all',
text: 'Retry All',
icon: 'retry',
},
{
type: 'clear',
text: 'Clear',
icon: 'delete',
},
{
type: 'clear-all',
text: 'Clear All Records',
icon: 'delete',
},
];

export const UploadActionButton = React.memo(function UploadActionButton({
Expand All @@ -42,6 +64,19 @@ export const UploadActionButton = React.memo(function UploadActionButton({
const dispatch = useAppDispatch();
const actionItem = actionItems.find((item) => item.type === type);

const onCancel = useCallback(
(ids: number[]) => {
dispatch(
updateUploadStatus({
account: loginAccount,
ids,
status: 'CANCEL',
}),
);
dispatch(cancelUploadingRequests({ ids }));
},
[dispatch, loginAccount],
);
const onClear = (ids: number[]) => {
dispatch(clearUploadRecords({ ids, loginAccount }));
};
Expand All @@ -50,14 +85,18 @@ export const UploadActionButton = React.memo(function UploadActionButton({
};
const onClick = () => {
switch (type) {
case 'clear':
case 'clear-all':
onClear(ids);
case 'cancel':
case 'cancel-all':
onCancel(ids);
break;
case 'retry':
case 'retry-all':
onRetry(ids);
break;
case 'clear':
case 'clear-all':
onClear(ids);
break;
default:
break;
}
Expand Down
15 changes: 10 additions & 5 deletions apps/dcellar-web-ui/src/modules/upload/UploadingObjects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { UploadingPanelKey, useTaskManagementTab } from './useTaskManagementTab'

import { IconFont } from '@/components/IconFont';
import { UploadingObjectsList } from './UploadingObjectsList';
import { UploadObject } from '@/store/slices/global';
import { UPLOADING_STATUSES, UPLOAD_FAILED_STATUSES, UploadObject } from '@/store/slices/global';
import { UploadActionButton } from './UploadActionButton';

interface UploadingObjectsProps {}
Expand All @@ -36,15 +36,20 @@ export const UploadingObjects = memo<UploadingObjectsProps>(function UploadingOb
panelKey: UploadingPanelKey;
data: UploadObject[];
}) => {
if ([UploadingPanelKey.ALL, UploadingPanelKey.UPLOADING].includes(panelKey)) {
return null;
}
return (
<Flex mb={12}>
{panelKey === UploadingPanelKey.COMPLETE && (
<UploadActionButton type="clear-all" ids={data.map((item) => item.id)} />
)}
{panelKey === UploadingPanelKey.FAILED && (
{(panelKey === UploadingPanelKey.UPLOADING || panelKey === UploadingPanelKey.ALL) && (
<UploadActionButton
type="cancel-all"
ids={data
.filter((item) => UPLOADING_STATUSES.includes(item.status))
.map((item) => item.id)}
/>
)}
{(panelKey === UploadingPanelKey.FAILED || panelKey === UploadingPanelKey.STOPPED) && (
<Flex gap={6}>
<UploadActionButton type="retry-all" ids={data.map((item) => item.id)} />
<UploadActionButton type="clear-all" ids={data.map((item) => item.id)} />
Expand Down
43 changes: 26 additions & 17 deletions apps/dcellar-web-ui/src/modules/upload/UploadingObjectsList.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { DCTable } from '@/components/common/DCTable';
import {
UPLOADING_STATUSES,
UPLOAD_FAILED_STATUSES,
UPLOAD_SUCCESS_STATUS,
UploadObject,
} from '@/store/slices/global';
import { UploadObject } from '@/store/slices/global';
import { ColumnProps } from 'antd/es/table';
import React, { useState } from 'react';
import { NameItem } from './NameItem';
Expand Down Expand Up @@ -34,7 +29,6 @@ export const UploadingObjectsList = ({ data }: { data: UploadObject[] }) => {
size={record.waitObject.size}
msg={record.msg}
status={record.status}
w={234}
task={record}
/>
);
Expand Down Expand Up @@ -72,23 +66,38 @@ export const UploadingObjectsList = ({ data }: { data: UploadObject[] }) => {
title: 'Action',
width: 146,
render: (record) => {
if (UPLOADING_STATUSES.includes(record.status)) {
const { status, id } = record;
if (['SEAL', 'SEALING'].includes(status)) {
return (
<Text color="readable.disable" fontSize={12}>
--
</Text>
);
}

if (UPLOAD_SUCCESS_STATUS === record.status) {
return <UploadActionButton type="clear" text="Clear Record" ids={[record.id]} />;
} else if (UPLOAD_FAILED_STATUSES.includes(record.status)) {
return (
<Flex gap={6}>
<UploadActionButton type="retry" ids={[record.id]} />
<UploadActionButton type="clear" ids={[record.id]} />
</Flex>
);
switch (status) {
case 'FINISH':
return <UploadActionButton type="clear" text="Clear Record" ids={[id]} />;

case 'CANCEL':
case 'ERROR':
return (
<Flex gap={6}>
<UploadActionButton type="retry" ids={[id]} />
<UploadActionButton type="clear" ids={[id]} />
</Flex>
);

case 'WAIT':
case 'HASH':
case 'HASHED':
case 'SIGN':
case 'SIGNED':
case 'UPLOAD':
return <UploadActionButton type="cancel" text="Cancel" ids={[id]} />;

default:
return null;
}
},
},
Expand Down
22 changes: 14 additions & 8 deletions apps/dcellar-web-ui/src/modules/upload/useTaskManagementTab.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { useAppSelector } from '@/store';
import { UploadObject } from '@/store/slices/global';
import { UPLOADING_STATUSES, UploadObject } from '@/store/slices/global';

import { sortBy } from 'lodash-es';
import { useMemo, useState } from 'react';

export enum UploadingPanelKey {
ALL = 'ALL',
UPLOADING = 'HASH-UPLOAD-SEAL',
UPLOADING = 'RETRY-WAIT-HASH-UPLOAD-SIGN-SEAL',
STOPPED = 'CANCEL',
COMPLETE = 'FINISH',
FAILED = 'ERROR-CANCEL',
FAILED = 'ERROR',
}

export const useTaskManagementTab = () => {
Expand All @@ -17,14 +18,14 @@ export const useTaskManagementTab = () => {

const queue = sortBy(objectUploadQueue[loginAccount] || [], (o) => o.waitObject.time);

const { uploadingQueue, completeQueue, errorQueue } = useMemo(() => {
const uploadingQueue = queue?.filter((i) =>
['HASH', 'UPLOAD', 'SEAL', 'SEALING'].includes(i.status),
);
const { uploadingQueue, stoppedQueue, completeQueue, errorQueue } = useMemo(() => {
const uploadingQueue = queue?.filter((i) => UPLOADING_STATUSES.includes(i.status));
const completeQueue = queue?.filter((i) => i.status === 'FINISH');
const errorQueue = queue?.filter((i) => ['ERROR', 'CANCEL'].includes(i.status));
const stoppedQueue = queue?.filter((i) => i.status === 'CANCEL');
const errorQueue = queue?.filter((i) => ['ERROR'].includes(i.status));
return {
uploadingQueue,
stoppedQueue,
completeQueue,
errorQueue,
};
Expand All @@ -46,6 +47,11 @@ export const useTaskManagementTab = () => {
key: UploadingPanelKey.UPLOADING,
data: uploadingQueue,
},
{
title: 'Stopped',
key: UploadingPanelKey.STOPPED,
data: stoppedQueue,
},
{
title: 'Complete',
key: UploadingPanelKey.COMPLETE,
Expand Down
2 changes: 1 addition & 1 deletion apps/dcellar-web-ui/src/pages/_document.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default function Document() {
__html: `window.__ASSET_PREFIX = ${flatted.stringify(assetPrefix)}`,
}}
></script>
<script defer src={`${assetPrefix}/js/iconfont_v0.1.2.min.js`}></script>
<script defer src={`${assetPrefix}/js/iconfont_v0.1.12.min.js`}></script>
<script defer src={`${assetPrefix}/wasm/tinygo_wasm_exec_v1.js`}></script>
<script defer src={`${assetPrefix}/wasm/tinygo_init_v1.js`}></script>
<EthereumScript />
Expand Down
Loading

0 comments on commit af91da1

Please sign in to comment.