From 5bea353ad3f537e5d4db308ed8c1310498843e1c Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 11 Dec 2019 10:06:31 +0300 Subject: [PATCH 1/5] Task name displayed better --- cvat-ui/src/components/tasks-page/task-item.tsx | 3 ++- cvat-ui/src/stylesheet.css | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cvat-ui/src/components/tasks-page/task-item.tsx b/cvat-ui/src/components/tasks-page/task-item.tsx index c7322cf5..915df3c3 100644 --- a/cvat-ui/src/components/tasks-page/task-item.tsx +++ b/cvat-ui/src/components/tasks-page/task-item.tsx @@ -49,7 +49,8 @@ class TaskItemComponent extends React.PureComponent - {`${id} ${name}`} + {`#${id}: `} + {name}
{ owner && ( diff --git a/cvat-ui/src/stylesheet.css b/cvat-ui/src/stylesheet.css index e8772391..d553f7bd 100644 --- a/cvat-ui/src/stylesheet.css +++ b/cvat-ui/src/stylesheet.css @@ -48,7 +48,7 @@ } .cvat-black-color { - color: black; + color: #363435; } .cvat-feedback-button { From 68e7b5289c0f7accf7d92911fcb208ad41b8ee62 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 11 Dec 2019 10:40:38 +0300 Subject: [PATCH 2/5] Improved tasks routing --- cvat-ui/src/components/header/header.tsx | 2 +- .../src/components/tasks-page/tasks-page.tsx | 84 ++++++++++++------- 2 files changed, 55 insertions(+), 31 deletions(-) diff --git a/cvat-ui/src/components/header/header.tsx b/cvat-ui/src/components/header/header.tsx index 707d7de6..69b76e22 100644 --- a/cvat-ui/src/components/header/header.tsx +++ b/cvat-ui/src/components/header/header.tsx @@ -57,7 +57,7 @@ function HeaderContainer(props: Props): JSX.Element { type='link' value='tasks' onClick={ - (): void => props.history.push('/tasks') + (): void => props.history.push('/tasks?page=1') } > Tasks diff --git a/cvat-ui/src/components/tasks-page/tasks-page.tsx b/cvat-ui/src/components/tasks-page/tasks-page.tsx index a0ebf786..e0633f28 100644 --- a/cvat-ui/src/components/tasks-page/tasks-page.tsx +++ b/cvat-ui/src/components/tasks-page/tasks-page.tsx @@ -43,6 +43,31 @@ function getSearchField(gettingQuery: TasksQuery): string { return searchString.slice(0, -5); } +function updateQuery(previousQuery: TasksQuery, searchString: string): TasksQuery { + const params = new URLSearchParams(searchString); + const query = { ...previousQuery }; + for (const field of Object.keys(query)) { + if (params.has(field)) { + const value = params.get(field); + if (value) { + if (field === 'id' || field === 'page') { + if (Number.isInteger(+value)) { + query[field] = +value; + } + } else { + query[field] = value; + } + } + } else if (field === 'page') { + query[field] = 1; + } else { + query[field] = null; + } + } + + return query; +} + class TasksPageComponent extends React.PureComponent { public componentDidMount(): void { const { @@ -50,38 +75,30 @@ class TasksPageComponent extends React.PureComponent { + public componentDidUpdate(prevProps: TasksPageProps & RouteComponentProps): void { const { + location, gettingQuery, onGetTasks, } = this.props; + if (prevProps.location.search !== location.search) { + // get new tasks if any query changes + const query = updateQuery(gettingQuery, location.search); + onGetTasks(query); + } + } + + private handleSearch = (value: string): void => { + const { + gettingQuery, + } = this.props; + const query = { ...gettingQuery }; const search = value.replace(/\s+/g, ' ').replace(/\s*:+\s*/g, ':').trim(); @@ -114,19 +131,19 @@ class TasksPageComponent extends React.PureComponent { const { gettingQuery, - onGetTasks, } = this.props; - const query = { ...gettingQuery }; + // modify query object + const query = { ...gettingQuery }; query.page = page; + + // update url according to new query object this.updateURL(query); - onGetTasks(query); }; private updateURL(gettingQuery: TasksQuery): void { @@ -137,9 +154,16 @@ class TasksPageComponent extends React.PureComponent Date: Wed, 11 Dec 2019 11:39:48 +0300 Subject: [PATCH 3/5] Ability to show hidden task --- cvat-ui/src/actions/tasks-actions.ts | 16 ++++++++-- .../src/components/tasks-page/task-item.tsx | 10 ++++++- .../src/components/tasks-page/tasks-page.tsx | 29 +++++++++++++++++++ .../src/containers/tasks-page/task-item.tsx | 2 ++ .../src/containers/tasks-page/tasks-page.tsx | 13 ++++++++- cvat-ui/src/reducers/interfaces.ts | 1 + cvat-ui/src/reducers/tasks-reducer.ts | 14 +++++++-- 7 files changed, 77 insertions(+), 8 deletions(-) diff --git a/cvat-ui/src/actions/tasks-actions.ts b/cvat-ui/src/actions/tasks-actions.ts index 1dfccf7f..015c12ff 100644 --- a/cvat-ui/src/actions/tasks-actions.ts +++ b/cvat-ui/src/actions/tasks-actions.ts @@ -30,7 +30,7 @@ export enum TasksActionTypes { UPDATE_TASK = 'UPDATE_TASK', UPDATE_TASK_SUCCESS = 'UPDATE_TASK_SUCCESS', UPDATE_TASK_FAILED = 'UPDATE_TASK_FAILED', - RESET_ERROR = 'RESET_ERROR', + HIDE_EMPTY_TASKS = 'HIDE_EMPTY_TASKS', } function getTasks(): AnyAction { @@ -90,8 +90,7 @@ ThunkAction, {}, {}, AnyAction> { return; } - const array = Array.from(result) - .filter((task: any) => task.jobs.length > 0); + const array = Array.from(result); const previews = []; const promises = array .map((task): string => (task as any).frames.preview()); @@ -513,3 +512,14 @@ ThunkAction, {}, {}, AnyAction> { } }; } + +export function hideEmptyTasks(hideEmpty: boolean): AnyAction { + const action = { + type: TasksActionTypes.HIDE_EMPTY_TASKS, + payload: { + hideEmpty, + }, + }; + + return action; +} diff --git a/cvat-ui/src/components/tasks-page/task-item.tsx b/cvat-ui/src/components/tasks-page/task-item.tsx index 915df3c3..dcf2a5c5 100644 --- a/cvat-ui/src/components/tasks-page/task-item.tsx +++ b/cvat-ui/src/components/tasks-page/task-item.tsx @@ -21,6 +21,7 @@ export interface TaskItemProps { taskInstance: any; previewImage: string; deleted: boolean; + hidden: boolean; activeInference: ActiveInference | null; } @@ -181,13 +182,20 @@ class TaskItemComponent extends React.PureComponent {this.renderPreview()} diff --git a/cvat-ui/src/components/tasks-page/tasks-page.tsx b/cvat-ui/src/components/tasks-page/tasks-page.tsx index e0633f28..f97bae65 100644 --- a/cvat-ui/src/components/tasks-page/tasks-page.tsx +++ b/cvat-ui/src/components/tasks-page/tasks-page.tsx @@ -4,8 +4,12 @@ import { withRouter } from 'react-router-dom'; import { Spin, + Button, + message, } from 'antd'; +import Text from 'antd/lib/typography/Text'; + import { TasksQuery, } from '../../reducers/interfaces'; @@ -19,7 +23,9 @@ interface TasksPageProps { gettingQuery: TasksQuery; numberOfTasks: number; numberOfVisibleTasks: number; + numberOfHiddenTasks: number; onGetTasks: (gettingQuery: TasksQuery) => void; + hideEmptyTasks: (hideEmpty: boolean) => void; } function getSearchField(gettingQuery: TasksQuery): string { @@ -85,12 +91,35 @@ class TasksPageComponent extends React.PureComponent + + Some tasks have not been showed because they do not have any data. + + + , 7, + ); } } diff --git a/cvat-ui/src/containers/tasks-page/task-item.tsx b/cvat-ui/src/containers/tasks-page/task-item.tsx index 38e5c193..9aa96727 100644 --- a/cvat-ui/src/containers/tasks-page/task-item.tsx +++ b/cvat-ui/src/containers/tasks-page/task-item.tsx @@ -15,6 +15,7 @@ import { interface StateToProps { deleted: boolean; + hidden: boolean; previewImage: string; taskInstance: any; activeInference: ActiveInference | null; @@ -35,6 +36,7 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps { const id = own.taskID; return { + hidden: state.tasks.hideEmpty && task.instance.jobs.length === 0, deleted: deletes.byTask[id] ? deletes.byTask[id] === true : false, previewImage: task.preview, taskInstance: task.instance, diff --git a/cvat-ui/src/containers/tasks-page/tasks-page.tsx b/cvat-ui/src/containers/tasks-page/tasks-page.tsx index 006e2c7d..5e1c21f5 100644 --- a/cvat-ui/src/containers/tasks-page/tasks-page.tsx +++ b/cvat-ui/src/containers/tasks-page/tasks-page.tsx @@ -2,23 +2,29 @@ import React from 'react'; import { connect } from 'react-redux'; import { + Task, TasksQuery, CombinedState, } from '../../reducers/interfaces'; import TasksPageComponent from '../../components/tasks-page/tasks-page'; -import { getTasksAsync } from '../../actions/tasks-actions'; +import { + getTasksAsync, + hideEmptyTasks, +} from '../../actions/tasks-actions'; interface StateToProps { tasksFetching: boolean; gettingQuery: TasksQuery; numberOfTasks: number; numberOfVisibleTasks: number; + numberOfHiddenTasks: number; } interface DispatchToProps { onGetTasks: (gettingQuery: TasksQuery) => void; + hideEmptyTasks: (hideEmpty: boolean) => void; } function mapStateToProps(state: CombinedState): StateToProps { @@ -29,6 +35,8 @@ function mapStateToProps(state: CombinedState): StateToProps { gettingQuery: tasks.gettingQuery, numberOfTasks: state.tasks.count, numberOfVisibleTasks: state.tasks.current.length, + numberOfHiddenTasks: tasks.hideEmpty ? tasks.current + .filter((task: Task) => !task.instance.jobs.length).length : 0, }; } @@ -37,6 +45,9 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { onGetTasks: (query: TasksQuery): void => { dispatch(getTasksAsync(query)); }, + hideEmptyTasks: (hideEmpty: boolean): void => { + dispatch(hideEmptyTasks(hideEmpty)); + }, }; } diff --git a/cvat-ui/src/reducers/interfaces.ts b/cvat-ui/src/reducers/interfaces.ts index 6a185646..138c0bce 100644 --- a/cvat-ui/src/reducers/interfaces.ts +++ b/cvat-ui/src/reducers/interfaces.ts @@ -24,6 +24,7 @@ export interface Task { export interface TasksState { initialized: boolean; fetching: boolean; + hideEmpty: boolean; gettingQuery: TasksQuery; count: number; current: Task[]; diff --git a/cvat-ui/src/reducers/tasks-reducer.ts b/cvat-ui/src/reducers/tasks-reducer.ts index cb6c975f..eed41a78 100644 --- a/cvat-ui/src/reducers/tasks-reducer.ts +++ b/cvat-ui/src/reducers/tasks-reducer.ts @@ -7,6 +7,7 @@ import { TasksState, Task } from './interfaces'; const defaultState: TasksState = { initialized: false, fetching: false, + hideEmpty: false, count: 0, current: [], gettingQuery: { @@ -51,6 +52,10 @@ export default (state: TasksState = defaultState, action: AnyAction): TasksState }, initialized: false, fetching: true, + hideEmpty: true, + count: 0, + current: [], + gettingQuery: { ...action.payload.query }, }; case TasksActionTypes.GET_TASKS_SUCCESS: { const combinedWithPreviews = action.payload.array @@ -73,9 +78,6 @@ export default (state: TasksState = defaultState, action: AnyAction): TasksState ...state, initialized: true, fetching: false, - count: 0, - current: [], - gettingQuery: { ...action.payload.query }, }; case TasksActionTypes.DUMP_ANNOTATIONS: { const { task } = action.payload; @@ -405,6 +407,12 @@ export default (state: TasksState = defaultState, action: AnyAction): TasksState }), }; } + case TasksActionTypes.HIDE_EMPTY_TASKS: { + return { + ...state, + hideEmpty: action.payload.hideEmpty, + }; + } case AuthActionTypes.LOGOUT_SUCCESS: { return { ...defaultState, From d419b44090d83f6e56e9a8a99e3599e5cc34e493 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 11 Dec 2019 11:43:48 +0300 Subject: [PATCH 4/5] Destroy messages before getting new tasks --- cvat-ui/src/components/tasks-page/tasks-page.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/cvat-ui/src/components/tasks-page/tasks-page.tsx b/cvat-ui/src/components/tasks-page/tasks-page.tsx index f97bae65..2f640c43 100644 --- a/cvat-ui/src/components/tasks-page/tasks-page.tsx +++ b/cvat-ui/src/components/tasks-page/tasks-page.tsx @@ -98,6 +98,7 @@ class TasksPageComponent extends React.PureComponent Date: Wed, 11 Dec 2019 12:09:48 +0300 Subject: [PATCH 5/5] Fixed eslint --- cvat-ui/src/containers/tasks-page/tasks-page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat-ui/src/containers/tasks-page/tasks-page.tsx b/cvat-ui/src/containers/tasks-page/tasks-page.tsx index 5e1c21f5..7e404d0e 100644 --- a/cvat-ui/src/containers/tasks-page/tasks-page.tsx +++ b/cvat-ui/src/containers/tasks-page/tasks-page.tsx @@ -36,7 +36,7 @@ function mapStateToProps(state: CombinedState): StateToProps { numberOfTasks: state.tasks.count, numberOfVisibleTasks: state.tasks.current.length, numberOfHiddenTasks: tasks.hideEmpty ? tasks.current - .filter((task: Task) => !task.instance.jobs.length).length : 0, + .filter((task: Task): boolean => !task.instance.jobs.length).length : 0, }; }