task-page.tsx 5.3 KB
Newer Older
K
Kirill Lakhov 已提交
1
// Copyright (C) 2020-2022 Intel Corporation
2
// Copyright (C) 2022-2023 CVAT.ai Corporation
B
Boris Sekachev 已提交
3 4 5
//
// SPDX-License-Identifier: MIT

B
Boris Sekachev 已提交
6
import './styles.scss';
7 8
import React, { useEffect, useRef, useState } from 'react';
import { useHistory, useParams } from 'react-router';
B
Boris Sekachev 已提交
9
import { useDispatch, useSelector } from 'react-redux';
10 11 12
import { Row, Col } from 'antd/lib/grid';
import Spin from 'antd/lib/spin';
import Result from 'antd/lib/result';
13
import notification from 'antd/lib/notification';
14

B
Boris Sekachev 已提交
15
import { getInferenceStatusAsync } from 'actions/models-actions';
16 17
import { getCore, Task, Job } from 'cvat-core-wrapper';
import JobListComponent from 'components/task-page/job-list';
18
import ModelRunnerModal from 'components/model-runner-modal/model-runner-dialog';
K
Kirill Lakhov 已提交
19
import CVATLoadingSpinner from 'components/common/loading-spinner';
20
import MoveTaskModal from 'components/move-task-modal/move-task-modal';
21
import { CombinedState } from 'reducers';
22
import TopBarComponent from './top-bar';
23
import DetailsComponent from './details';
24

25
const core = getCore();
B
Boris Sekachev 已提交
26

27 28 29
function TaskPageComponent(): JSX.Element {
    const history = useHistory();
    const id = +useParams<{ id: string }>().id;
B
Boris Sekachev 已提交
30
    const dispatch = useDispatch();
31 32 33 34
    const [taskInstance, setTaskInstance] = useState<Task | null>(null);
    const [fetchingTask, setFetchingTask] = useState(true);
    const [updatingTask, setUpdatingTask] = useState(false);
    const mounted = useRef(false);
B
Boris Sekachev 已提交
35

36
    const deletes = useSelector((state: CombinedState) => state.tasks.activities.deletes);
B
Boris Sekachev 已提交
37

38 39 40 41 42 43 44 45 46 47
    const receieveTask = (): void => {
        if (Number.isInteger(id)) {
            core.tasks.get({ id })
                .then(([task]: Task[]) => {
                    if (task && mounted.current) {
                        setTaskInstance(task);
                    }
                }).catch((error: Error) => {
                    if (mounted.current) {
                        notification.error({
48
                            message: 'Could not receive the requested task from the server',
49 50 51 52 53 54 55 56 57 58 59 60 61 62
                            description: error.toString(),
                        });
                    }
                }).finally(() => {
                    if (mounted.current) {
                        setFetchingTask(false);
                    }
                });
        } else {
            notification.error({
                message: 'Could not receive the requested task from the server',
                description: `Requested task id "${id}" is not valid`,
            });
            setFetchingTask(false);
63
        }
64
    };
65

66 67
    useEffect(() => {
        receieveTask();
B
Boris Sekachev 已提交
68
        dispatch(getInferenceStatusAsync());
69 70 71 72 73
        mounted.current = true;
        return () => {
            mounted.current = false;
        };
    }, []);
74

75 76 77
    useEffect(() => {
        if (taskInstance && id in deletes && deletes[id]) {
            history.push('/tasks');
B
Boris Sekachev 已提交
78
        }
79
    }, [deletes]);
B
Boris Sekachev 已提交
80

81 82 83
    if (fetchingTask) {
        return <Spin size='large' className='cvat-spinner' />;
    }
B
Boris Sekachev 已提交
84

85
    if (!taskInstance) {
B
Boris Sekachev 已提交
86
        return (
87 88 89 90 91 92
            <Result
                className='cvat-not-found'
                status='404'
                title='There was something wrong during getting the task'
                subTitle='Please, be sure, that information you tried to get exist and you are eligible to access it'
            />
B
Boris Sekachev 已提交
93
        );
94
    }
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

    const onUpdateTask = (task: Task): Promise<void> => (
        new Promise((resolve, reject) => {
            setUpdatingTask(true);
            task.save().then((updatedTask: Task) => {
                if (mounted.current) {
                    setTaskInstance(updatedTask);
                }
                resolve();
            }).catch((error: Error) => {
                notification.error({
                    message: 'Could not update the task',
                    className: 'cvat-notification-notice-update-task-failed',
                    description: error.toString(),
                });
                reject();
            }).finally(() => {
                if (mounted.current) {
                    setUpdatingTask(false);
                }
            });
        })
    );

    const onJobUpdate = (job: Job): void => {
        setUpdatingTask(true);
        job.save().then(() => {
            if (mounted.current) {
                receieveTask();
            }
        }).catch((error: Error) => {
            notification.error({
                message: 'Could not update the job',
                description: error.toString(),
            });
        }).finally(() => {
            if (mounted.current) {
                setUpdatingTask(false);
            }
        });
    };

    return (
        <div className='cvat-task-page'>
            { updatingTask ? <CVATLoadingSpinner size='large' /> : null }
            <Row
                justify='center'
                align='top'
                className='cvat-task-details-wrapper'
            >
K
klakhov 已提交
145
                <Col span={22} xl={18} xxl={14}>
146 147 148 149 150 151 152 153 154
                    <TopBarComponent taskInstance={taskInstance} />
                    <DetailsComponent task={taskInstance} onUpdateTask={onUpdateTask} />
                    <JobListComponent task={taskInstance} onUpdateJob={onJobUpdate} />
                </Col>
            </Row>
            <ModelRunnerModal />
            <MoveTaskModal onUpdateTask={onUpdateTask} />
        </div>
    );
155 156
}

157
export default React.memo(TaskPageComponent);