From b0b36312e733ab8b402f0bf84b29421e4a900ced Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Thu, 8 Apr 2021 22:55:29 +0300 Subject: [PATCH] Some client code refactoring (#3077) * Some refactoring, fixed unnesasary rerenderss * Refactored filter * Refactored filter * Removed extra call of queryString() method --- cvat-core/src/project.js | 56 ++++++++++++------- cvat-ui/src/actions/annotation-actions.ts | 5 +- .../annotation-page/annotation-page.tsx | 4 +- .../objects-side-bar/labels-list.tsx | 14 ++--- .../annotation-page/top-bar/filters-modal.tsx | 39 +++++++------ .../annotation-page/top-bar/right-group.tsx | 12 ++-- .../create-project-content.tsx | 23 +++----- cvat-ui/src/components/cvat-app.tsx | 9 +-- .../components/layout-grid/layout-grid.tsx | 3 +- .../annotation-page/top-bar/filters-modal.tsx | 26 --------- cvat-ui/src/index.tsx | 9 +-- cvat-ui/src/reducers/annotation-reducer.ts | 4 ++ 12 files changed, 100 insertions(+), 104 deletions(-) delete mode 100644 cvat-ui/src/containers/annotation-page/top-bar/filters-modal.tsx diff --git a/cvat-core/src/project.js b/cvat-core/src/project.js index f4609d9d0a00..0e2b54789141 100644 --- a/cvat-core/src/project.js +++ b/cvat-core/src/project.js @@ -65,8 +65,8 @@ } data.task_subsets = Array.from(subsetsSet); } - if (initialData.training_project) { - data.training_project = JSON.parse(JSON.stringify(initialData.training_project)); + if (typeof initialData.training_project === 'object') { + data.training_project = { ...initialData.training_project }; } Object.defineProperties( @@ -222,21 +222,34 @@ subsets: { get: () => [...data.task_subsets], }, - - _internalData: { - get: () => data, - }, - - training_project: { - get: () => data.training_project, - set: (training) => { - if (training) { - data.training_project = JSON.parse(JSON.stringify(training)); + /** + * Training project associated with this annotation project + * This is a simple object which contains + * keys like host, username, password, enabled, project_class + * @name trainingProject + * @type {object} + * @memberof module:API.cvat.classes.Project + * @readonly + * @instance + */ + trainingProject: { + get: () => { + if (typeof data.training_project === 'object') { + return { ...data.training_project }; + } + return data.training_project; + }, + set: (updatedProject) => { + if (typeof training === 'object') { + data.training_project = { ...updatedProject }; } else { - data.training_project = training; + data.training_project = updatedProject; } }, }, + _internalData: { + get: () => data, + }, }), ); } @@ -278,33 +291,38 @@ }; Project.prototype.save.implementation = async function () { - let trainingProject; - if (this.training_project) { - trainingProject = JSON.parse(JSON.stringify(this.training_project)); - } + const trainingProjectCopy = this.trainingProject; if (typeof this.id !== 'undefined') { + // project has been already created, need to update some data const projectData = { name: this.name, assignee_id: this.assignee ? this.assignee.id : null, bug_tracker: this.bugTracker, labels: [...this._internalData.labels.map((el) => el.toJSON())], - training_project: trainingProject, }; + if (trainingProjectCopy) { + projectData.training_project = trainingProjectCopy; + } + await serverProxy.projects.save(this.id, projectData); return this; } + // initial creating const projectSpec = { name: this.name, labels: [...this.labels.map((el) => el.toJSON())], - training_project: trainingProject, }; if (this.bugTracker) { projectSpec.bug_tracker = this.bugTracker; } + if (trainingProjectCopy) { + projectSpec.training_project = trainingProjectCopy; + } + const project = await serverProxy.projects.create(projectSpec); return new Project(project); }; diff --git a/cvat-ui/src/actions/annotation-actions.ts b/cvat-ui/src/actions/annotation-actions.ts index a7afc3b1bd9f..898306a0aea1 100644 --- a/cvat-ui/src/actions/annotation-actions.ts +++ b/cvat-ui/src/actions/annotation-actions.ts @@ -1068,7 +1068,10 @@ export function getJobAsync(tid: number, jid: number, initialFrame: number, init setTimeout(updatePredictorStatus, 20 * 1000); } }; - updatePredictorStatus(); + + if (state.plugins.list.PREDICT && job.task.projectId !== null) { + updatePredictorStatus(); + } dispatch(changeFrameAsync(frameNumber, false)); } catch (error) { diff --git a/cvat-ui/src/components/annotation-page/annotation-page.tsx b/cvat-ui/src/components/annotation-page/annotation-page.tsx index 3d1324a0fc3b..5bedffaa0bdb 100644 --- a/cvat-ui/src/components/annotation-page/annotation-page.tsx +++ b/cvat-ui/src/components/annotation-page/annotation-page.tsx @@ -16,7 +16,7 @@ import SubmitReviewModal from 'components/annotation-page/review/submit-review-m import StandardWorkspaceComponent from 'components/annotation-page/standard-workspace/standard-workspace'; import StandardWorkspace3DComponent from 'components/annotation-page/standard3D-workspace/standard3D-workspace'; import TagAnnotationWorkspace from 'components/annotation-page/tag-annotation-workspace/tag-annotation-workspace'; -import FiltersModalContainer from 'containers/annotation-page/top-bar/filters-modal'; +import FiltersModalComponent from 'components/annotation-page/top-bar/filters-modal'; import StatisticsModalContainer from 'containers/annotation-page/top-bar/statistics-modal'; import AnnotationTopBarContainer from 'containers/annotation-page/top-bar/top-bar'; import { Workspace } from 'reducers/interfaces'; @@ -131,7 +131,7 @@ export default function AnnotationPageComponent(props: Props): JSX.Element { )} - + diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/labels-list.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/labels-list.tsx index b0955de0bed7..99ee07ea267f 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/labels-list.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/labels-list.tsx @@ -13,14 +13,12 @@ import GlobalHotKeys from 'utils/mousetrap-react'; function LabelsListComponent(): JSX.Element { const dispatch = useDispatch(); - const { - annotation: { - job: { labels }, - tabContentHeight: listHeight, - annotations: { activatedStateID, states }, - }, - shortcuts: { keyMap }, - } = useSelector((state: CombinedState) => state); + const labels = useSelector((state: CombinedState) => state.annotation.job.labels); + const listHeight = useSelector((state: CombinedState) => state.annotation.tabContentHeight); + const activatedStateID = useSelector((state: CombinedState) => state.annotation.annotations.activatedStateID); + const states = useSelector((state: CombinedState) => state.annotation.annotations.states); + const keyMap = useSelector((state: CombinedState) => state.shortcuts.keyMap); + const labelIDs = labels.map((label: any): number => label.id); const [keyToLabelMapping, setKeyToLabelMapping] = useState>( diff --git a/cvat-ui/src/components/annotation-page/top-bar/filters-modal.tsx b/cvat-ui/src/components/annotation-page/top-bar/filters-modal.tsx index dbc43d525e5d..e1a76101f5c5 100644 --- a/cvat-ui/src/components/annotation-page/top-bar/filters-modal.tsx +++ b/cvat-ui/src/components/annotation-page/top-bar/filters-modal.tsx @@ -23,19 +23,15 @@ const { FieldDropdown } = AntdWidgets; const FILTERS_HISTORY = 'annotationFiltersHistory'; -interface Props { - visible: boolean; -} - interface StoredFilter { id: string; logic: JsonLogicTree; } -export default function FiltersModalComponent(props: Props): JSX.Element { - const { visible } = props; - const { labels } = useSelector((state: CombinedState) => state.annotation.job); - const { filters: activeFilters } = useSelector((state: CombinedState) => state.annotation.annotations); +function FiltersModalComponent(): JSX.Element { + const labels = useSelector((state: CombinedState) => state.annotation.job.labels); + const activeFilters = useSelector((state: CombinedState) => state.annotation.annotations.filters); + const visible = useSelector((state: CombinedState) => state.annotation.filtersPanelVisible); const getConvertedInputType = (inputType: string): string => { switch (inputType) { @@ -234,18 +230,23 @@ export default function FiltersModalComponent(props: Props): JSX.Element { const menu = ( {filters - .filter((filter: StoredFilter) => { - const tree = QbUtils.loadFromJsonLogic(filter.logic, config); - return !!QbUtils.queryString(tree, config); - }) .map((filter: StoredFilter) => { + // if a logic received from local storage does not correspond to current config + // which depends on label specification + // (it can be when history from another task with another specification or when label was removed) + // loadFromJsonLogic() prints a warning to console + // the are not ways to configure this behaviour + const tree = QbUtils.loadFromJsonLogic(filter.logic, config); - return ( - setState({ tree, config })}> - {QbUtils.queryString(tree, config)} - - ); - })} + const queryString = QbUtils.queryString(tree, config); + return { tree, queryString, filter }; + }) + .filter(({ queryString }) => !!queryString) + .map(({ filter, tree, queryString }) => ( + setState({ tree, config })}> + {queryString} + + ))} ); @@ -286,3 +287,5 @@ export default function FiltersModalComponent(props: Props): JSX.Element { ); } + +export default React.memo(FiltersModalComponent); diff --git a/cvat-ui/src/components/annotation-page/top-bar/right-group.tsx b/cvat-ui/src/components/annotation-page/top-bar/right-group.tsx index b91e575fd905..c4727e6a43de 100644 --- a/cvat-ui/src/components/annotation-page/top-bar/right-group.tsx +++ b/cvat-ui/src/components/annotation-page/top-bar/right-group.tsx @@ -47,8 +47,8 @@ function RightGroup(props: Props): JSX.Element { isTrainingActive, showFilters, } = props; - predictor.annotationAmount = predictor.annotationAmount ? predictor.annotationAmount : 0; - predictor.mediaAmount = predictor.mediaAmount ? predictor.mediaAmount : 0; + const annotationAmount = predictor.annotationAmount || 0; + const mediaAmount = predictor.mediaAmount || 0; const formattedScore = `${(predictor.projectScore * 100).toFixed(0)}%`; const predictorTooltip = (
@@ -65,15 +65,15 @@ function RightGroup(props: Props): JSX.Element {
Annotations amount: - {predictor.annotationAmount} + {annotationAmount}
Media amount: - {predictor.mediaAmount} + {mediaAmount}
- {predictor.annotationAmount > 0 ? ( + {annotationAmount > 0 ? ( Model mAP is {' '} @@ -139,7 +139,7 @@ function RightGroup(props: Props): JSX.Element { - {predictor.annotationAmount ? `mAP ${formattedScore}` : 'not trained'} + {annotationAmount ? `mAP ${formattedScore}` : 'not trained'} )}